Scaling and operations
What one instance handles, what Redis buys you, how upgrades and staging work, and what to back up.
The default single-instance deployment scales to hundreds of concurrent users. The cost of an edit is proportional to the number of people live in that vault, not to how many accounts exist, and the vault channel is a stateless relay, so memory is bounded by the documents being edited rather than the documents that exist.
Going beyond one instance
For thousands of concurrent users, redundancy, or zero-downtime rolling deploys, run several instances behind a load balancer and set the same REDIS_URL on all of them.
- The vault replication channel fans out through Redis pub/sub, so a client can connect to any instance and still receive every document it is allowed to see.
- The editing path uses the Redis extension, so the same document edited live on two instances stays consistent.
- No sticky sessions are needed. Clients reconnect with jittered backoff, so a rolling deploy does not stampede.
cd app/apps/server
docker compose --profile ha up -d redis # host port 6389
REDIS_URL=redis://localhost:6389 pnpm run devUpgrades
Migrations run before the server starts, so an upgrade is a redeploy. With the Compose bundle that is git pull && docker compose up -d --build, and on Railway it is a redeploy from the latest release. The app's behind-the-server notice clears on its next check, within ten minutes, or at once after a restart or reconnect.
A staging instance
Run a second server for a staging build and set DEEP_LINK_SCHEME=baalda-staging on it, so links from production and from staging open the right app on a machine that has both installed.
What to back up
- Postgres. It holds identity, organizations, permissions, the registry and the binary document store, and attachment bytes too unless you moved them to S3.
- The S3 bucket, if you use one. It is not covered by a database backup.
- Nothing on the clients. Every device's vault folder is a full copy of the Markdown, which is the point of the design.
REDIS_URL unset and it behaves exactly as before, with Postgres alone.This page is written from docs/DEPLOY.md and docs/specs/05-vault-sync-engine.md in the repository. Those documents go further, and they are the ones that change first.
Read it on GitHubWas this page helpful?
