A database is a container, not a subscription
Backing services run through the exact same primitives as your app: a pinned image, bind-mounted data, a spot on the internal network. Pick an engine and version, bind an app to it, and Sproobo wires the connection string for you.
The engine catalog
Every service is a pinned, choosable version — never an implicit "latest". Today's catalog:
- PostgreSQL — 14 · 15 · 16 · 17
- MySQL — 8.0 · 8.4
- MariaDB — 10.11 · 11.4
- Redis — 7
- MongoDB — 7.0 · 8.0. The root user lives in the admin auth database, and a bound app's MONGO_URL always carries ?authSource=admin.
The version list is code-defined and versioned with the control plane, so it evolves — the picker always reflects exactly what's offered today, not this page.
On the roadmap: Elasticsearch is planned as a fast-follow engine (it carries a heavier memory and reindex profile than the others), and a custom-service escape hatch — bring your own image with a bind-mounted data dir — is planned too; neither is shipped yet.
Creating a service
From the dashboard's New service flow, or by having an MCP-native client — an AI agent, an editor connector — call the create_service tool over the same audited API. It's plan-first like every other write: a dry run unless the call carries approve: true, and it needs at least a MEMBER role. The CLI's sproobo services command lists what already exists; it doesn't provision a new one:
sproobo servicesHow a service actually runs
Provisioning compiles a plan from the same primitives as an app deploy — no separate machinery for databases:
Pull the pinned image
The exact engine:version you chose, e.g. postgres:16.
Bind-mount the data directory
Under /var/lib/sproobo/services/<id>/data — owner-inspectable, and excluded from any prune or cleanup sweep.
Start the container on the internal network
On sproobo-int only, with mandatory memory and CPU limits so one service can't starve the host or its neighbors, and a restart policy that can't race a cleanup sweep.
Health probe gates readiness
E.g. pg_isready for Postgres — the service isn't considered up until its probe passes.
Because the data directory is a stable bind mount, replacing a service's container means a brief moment of unavailability — never data loss. A version upgrade goes one step further: it restores into a fresh, separately versioned data directory and leaves the previous one intact on the box as a rollback. Stateful containers don't get the side-by-side blue-green swap apps do; the bind mount is what makes the replacement safe.
No published ports, ever
Backing services attach only to the internal sproobo-int Docker network — never -p-published to 0.0.0.0. Apps reach a service by its container DNS name on that same network; there's nothing listening on a public port for anything outside the box to find.
Binding an app to a service
Binding is what turns "a Postgres container exists" into "my app has a DATABASE_URL". From the service's page in the dashboard, bind an app in one click. On the app's next deploy, the service's connection string is injected into its environment automatically — DATABASE_URL for the SQL engines, MONGO_URL for MongoDB, REDIS_URL for Redis — pointing at the service's DNS name on sproobo-int.
Today that connection string carries the service's admin credentials — the ones generated when the service was created — so the bound app has full access to the service, including creating its own databases and schemas. The wiring is resolved fresh on every deploy, so it's reproducible rather than a one-off manual step, and unbinding removes it the same way on the next deploy.
On the roadmap: per-app auto-provisioning — a dedicated database plus a least-privilege user for each bound app, instead of the shared admin credentials — is designed but not yet wired into the product.
Version upgrades are never a bare tag bump
Picking a version at create time is free — but upgrading an existing service is its own gated operation, not a container restart with a new image tag. It requires a verified backup first and runs a dump-and-restore recipe into a fresh, separately versioned instance, so the version you're upgrading from is never touched or overwritten. See Backups & restore for the full mechanics — including why upgrade_service is the one write on the whole platform that can never be pre-approved for automation.
Free keeps 2 services per org, Pro up to 10, and Team and Enterprise are unlimited. See Pricing for the full breakdown.
Next
- Read the full backup, restore, and upgrade mechanics on Backups & restore.
- See how a service's injected env reaches your app's build and runtime on Apps & deploys.
- Read the full trust-boundary and data-ownership model on Security model.