Most hosting control panels and billing systems default to MySQL or MariaDB for everything: customer records, invoice line items, session data, configuration flags. Salieno Core doesn't. Our customer database, billing ledger, and account metadata all live in a single SQLite file on disk.
This wasn't a contrarian choice for its own sake. It was a deliberate engineering decision shaped by how single-server hosting businesses actually operate—and the operational headaches we wanted to eliminate.
The Problem with MySQL for Single-Server Panels#
When you're running a hosting business on one or two physical servers, MySQL introduces overhead that's easy to overlook until it bites you.
First, there's the daemon itself. MySQL or MariaDB needs to be installed, configured, tuned, secured, and monitored. It consumes a baseline of 200–400 MB of RAM even when idle. It writes to its own log files, rotates them, and occasionally crashes InnoDB recovery after an unclean shutdown. For a control panel that manages maybe a few hundred to a few thousand customer accounts, this is infrastructure overhead for infrastructure's sake.
Second, there's the connection model. PHP applications typically connect to MySQL over a TCP socket, authenticate, run a query, and disconnect—or hold a persistent connection that ties up a server thread. Under load, connection storms can starve the very web-serving processes your customers depend on. Tools like ProxySQL help, but now you're running middleware to manage middleware.
Third, and most subtly, there's the blast radius. If your MySQL instance goes down—corrupted table, disk full, OOM kill—your entire panel, billing system, and customer portal go down with it. Your customers' websites might still be running fine on Nginx and PHP-FPM, but they can't log in, can't pay invoices, and can't manage DNS. The control plane and the data plane share a failure domain.
What SQLite Gives Us Instead#
SQLite is a library, not a server. It reads and writes to a single file using filesystem locks. There's no daemon to manage, no TCP connections to pool, no authentication layer, and no separate memory footprint.
For Salieno Core, this means the customer database is just a file at a known path. The billing module opens it, runs its queries, and closes it. If Salieno Core is running, the database is available. If Salieno Core is stopped, the database file sits quietly on disk, immune to connection timeouts or daemon crashes.
The operational benefits are concrete:
- Zero configuration. No
my.cnfto tune, no buffer pool sizes to calculate, nomax_connectionsto stress-test. SQLite uses sensible defaults out of the box. - Simpler backups. The entire customer database is one file. You can back it up with a single
cpcommand (or better, use SQLite's.backupcommand for a consistent snapshot). No need formysqldumpor Percona XtraBackup. - Smaller resource footprint. On a server already running Nginx, PHP-FPM, Postfix, and a dozen cron jobs, not running a MySQL daemon frees up meaningful RAM for the workloads that actually serve customer traffic.
- Portable by default. Moving Salieno Core to a new server means copying the SQLite file alongside the application. No database export/import dance.
The Trade-Offs We Accepted#
SQLite isn't free of limitations, and we designed around them honestly.
Write concurrency. SQLite uses file-level locking for writes. Two processes can't write to the database simultaneously—one will wait. For a control panel where writes happen on account creation, billing events, and configuration changes (not thousands of concurrent writes per second), this is a non-issue. We measured our write patterns: even on a busy reseller server with 500 accounts, peak write concurrency is a few operations per minute.
No network access. You can't connect to a SQLite database from a remote server. This means Salieno Core's billing and account data lives on the same machine as the panel itself. For single-server and small multi-server setups, this is fine—and it's actually a security benefit, since the customer database isn't exposed on a network port.
No stored procedures or advanced SQL features. SQLite supports standard SQL but lacks MySQL-specific features like stored procedures, triggers with complex logic, and certain join optimizations. We kept our schema simple and our queries straightforward, which has the side benefit of making the codebase easier to audit.
Scaling ceiling. SQLite handles databases up to several hundred megabytes without breaking a sweat. For a hosting reseller managing a few thousand accounts, the database will be tens of megabytes at most. If you're running a platform with tens of thousands of accounts across multiple servers, you've outgrown a single-server control panel entirely—and at that point, you're evaluating different architectural choices altogether.
How We Handle Durability#
The most common objection to SQLite is data safety. "What if the power goes out mid-write?" SQLite's WAL (Write-Ahead Logging) mode, which we enable by default, provides transactional durability on par with any ACID-compliant database. Writes are atomic: they either complete fully or not at all. We also run PRAGMA integrity_check on startup to catch corruption early, though in practice we've never seen it in production.
For additional safety, Salieno Core's backup integration can snapshot the SQLite file on a schedule. Since it's a single file, incremental backups with tools like Restic are efficient—you're only storing changed pages, not a full logical dump.
When This Architecture Doesn't Fit#
If you're building a multi-tenant SaaS platform where hundreds of reseller accounts share a centralized backend, SQLite is the wrong tool. You need a networked database with connection pooling, replication, and horizontal scaling. That's a different product for a different market.
Salieno Core is built for the operator running their own infrastructure—a hosting reseller, an agency, an indie host. For that audience, simplicity and reliability beat scalability features they'll never use.
The Broader Principle#
Choosing SQLite wasn't just a database decision. It reflects a broader philosophy in Salieno Core's architecture: use the simplest tool that solves the problem correctly, and spend complexity budgets on things that directly improve the operator's experience—like the plugin system, the billing automation, or the API layer.
Every dependency you add to a self-hosted system is something the operator has to maintain. By keeping the database dependency at zero, we keep the operational surface smaller and the failure modes fewer. For a single-server hosting business, that's not a compromise—it's the right engineering call.
0 comments
Loading comments…