Database servers
Keep data off the app server: database servers, standbys, backups by default, PgBouncer, Postgres upgrades, forks with masking and outside URLs.
By default an app’s databases run on the same server as the app. That’s cheap and fast, but if that server is lost, only your backups survive. A database server is one of your own servers that only holds data.
Add a database server
Servers → + Add a database server. It works like adding a server, with a few differences:
- It gets no web proxy and no build tools, and apps are never deployed to it.
- Its datastore ports are open only to the app servers that use it.
- Its page lists the apps whose data it holds.
Choose where an app’s data lives
When you create an app, Where should the data live? offers three choices:
- This server: the app’s own server.
- A database server: preselected for production when your team has one.
- External: paste the URL of a managed service such as RDS, ElastiCache or Elastic Cloud.
For an existing app, go to Settings → Resources → Move data to a database server. The card lists what will be copied and what starts empty before you press the button. Then:
- The app stops.
- Postgres and MySQL are dumped and restored on the database server.
- Redis, MongoDB, object storage, RabbitMQ definitions and ClickHouse are copied too. An Elasticsearch that only this app uses is copied as well.
- The app redeploys.
If any step fails, the app goes back to its old data, which is only read and never changed. Memcached isn’t copied, and neither is an Elasticsearch shared with another app: reindex after the move.
Use an outside service on the Resources tab switches the database, Redis or Elasticsearch to a URL you give. Railyard checks the URL first. An unreachable one changes nothing, and your app isn’t stopped. You can copy the data across, and Bring back under Railyard reverses it.
Protected by default
- Backups. App databases on a database server get a backup every 24 hours, and each one is checked by restoring it. A schedule you set on the database card is kept.
- Standby (beta). Also create a standby on Add a database server creates a second server of the same size. Once both are up, it streams a copy of Postgres.
- Promote from the primary’s page (Maintenance → Postgres replicas) or from the standby’s own page. The standby becomes a writable Postgres on port 5433. Apps are not repointed automatically yet: set their
DATABASE_URLto the standby, or move their data.
You can also add a Postgres replica to any other team server from Maintenance → Postgres replicas.
Connection pooler (PgBouncer)
There are two switches:
- Server → Maintenance → Connection pooler → Turn on. This runs PgBouncer in transaction mode on port 6432. Rails’ prepared statements still work.
- App → Resources → Database card → Use the pooler. From the next deploy,
DATABASE_URLgoes through the pooler andDATABASE_DIRECT_URLkeeps the direct address.
The release step (migrations) always uses the direct address, because advisory locks don’t work through transaction pooling. Choosing the pooler for an app also starts it on the server if it isn’t running. You can’t turn a server’s pooler off while an app uses it.
Postgres major-version upgrades (beta)
Server → Maintenance → Postgres version.
- Check compatibility. This is a dry run and changes nothing. It checks each database’s extensions against the new version and makes sure there’s about twice the data size in free disk.
- Upgrade now, or In the next maintenance window. Railyard backs up every database first, and any failed backup stops the upgrade. Each database is copied into the new version and its tables are counted to confirm the copy. Then the new version takes over the same port, so apps keep their
DATABASE_URL. App logins are paused during the copy. - Roll back while the old version is kept (7 days by default). Anything written after the upgrade is not in the old version.
Fork a database
App → Resources → Database card → Fork this database (Postgres).
- Into: a new database on any server with Railyard-managed Postgres, which gets its own login and password. Or replace a staging or preview environment’s data. Production is never a target.
- From: a live copy taken now, or the latest backup.
- Mask: paste SQL, for example
UPDATE users SET email = 'user' || id || '@example.test', phone = NULL;. It runs on the copy before anyone can use it. If it fails, the copy is deleted, so there’s never an unmasked fork.
Per-column masking rules in the UI and instant copy-on-write forks aren’t built yet.
Maintenance windows
Set a weekly slot under Team → Maintenance, or per server under Settings → Data maintenance window. Railyard sends notice to rules with data maintenance ticked. Inside the window it runs scheduled Postgres upgrades, security updates on database servers and VACUUM (ANALYZE). With no window set, nothing runs on its own.
A dedicated Redis per app
By default apps share the server’s Redis, each with its own database number. Give this app its own Redis on the Redis card sets a memory limit and what happens when it’s full (an eviction policy such as allkeys-lru). Your keys are copied across. Go back to the shared Redis copies them back.
API
| Method | Path | Purpose |
|---|---|---|
| POST | /api/applications/:id/data_move | Move data to a database server (database_server_id) |
| POST / DELETE | /api/applications/:id/external_datastores | Use an outside URL, or bring the data back |
| GET / POST | /api/servers/:id/database_replicas | List or add standbys; POST …/:id/promote promotes |
| GET / POST / DELETE | /api/servers/:id/connection_pooler | The server’s PgBouncer |
| GET / POST | /api/servers/:id/postgres_upgrades | Check, schedule, roll back and clean up upgrades |
| GET / POST / DELETE | /api/applications/:id/database_forks | Forks (source is live or backup, optional mask_sql) |
| GET / PATCH | /api/applications/:id/redis | Shared or dedicated Redis, memory limit and policy |
Backups, restores and consoles are covered in Databases and backups.