Architecture
A Resta server is five containers from one Docker Compose file: a gateway that serves everything on one domain, the dashboard, an API, a data node that holds the databases, and Postgres for metadata. Apps query the node directly through the gateway; the API never sits in the query path.
Services
| Service | Role | Data |
|---|---|---|
gateway | Caddy. Routes /v1 to the API, /db to the node, everything else to the dashboard. TLS. | caddy volume |
dashboard | Static web UI. | none |
api | Account, API keys, database list, tokens, backup requests. | keys volume |
node | Stores and serves the databases; takes snapshots. | dbdata, backups volumes |
postgres | Metadata for the API. | pgdata volume |
Request flow
- Your backend calls
POST /v1/databaseswith an API key. The API records the database in Postgres and asks the node, over the internal network, to create its directory. - Your backend calls
POST /v1/databases/{name}/tokensand receives a signed JWT. - Your app sends SQL to
https://<server>/db/<id>/v3/pipelinewith that token. The gateway forwards it to the node, which checks the signature with the public key and runs the SQL.
Storage
Each database is its own directory on the node, holding a SQLite-format file and its write-ahead log. A database that was created but never written is just the directory. Databases open on first use and close after 5 minutes idle; at most 10,000 are open at once by default. Each database has one writer at a time; different databases write in parallel.
Commits are synced to disk before they are acknowledged. In testing, every acknowledged write survived the node being killed with SIGKILL, and the database passed PRAGMA integrity_check.
Capacity
These are estimates, not load-test results:
| State | Cost |
|---|---|
| Created, never written | A Postgres row and a directory |
| Written, idle | Its files on disk; small databases are tens of kilobytes |
| Open | About 2 file handles and some engine memory |
A small VPS should hold tens of thousands of databases with a few thousand open at once. The first limit to expect is the backup pass, which checks every database on each run; at the hourly default there is a lot of headroom.
Limits of the design
- One node on one machine: no replication or failover.
- The node restarts during upgrades.
- The default backup target is on the same disk as the data.
- Postgres needs its own backup.