Database servers
← Docs · Run in production

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:

  1. The app stops.
  2. Postgres and MySQL are dumped and restored on the database server.
  3. Redis, MongoDB, object storage, RabbitMQ definitions and ClickHouse are copied too. An Elasticsearch that only this app uses is copied as well.
  4. 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_URL to 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:

  1. Server → Maintenance → Connection pooler → Turn on. This runs PgBouncer in transaction mode on port 6432. Rails’ prepared statements still work.
  2. App → Resources → Database card → Use the pooler. From the next deploy, DATABASE_URL goes through the pooler and DATABASE_DIRECT_URL keeps 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.

  1. 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.
  2. 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.
  3. 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

MethodPathPurpose
POST/api/applications/:id/data_moveMove data to a database server (database_server_id)
POST / DELETE/api/applications/:id/external_datastoresUse an outside URL, or bring the data back
GET / POST/api/servers/:id/database_replicasList or add standbys; POST …/:id/promote promotes
GET / POST / DELETE/api/servers/:id/connection_poolerThe server’s PgBouncer
GET / POST/api/servers/:id/postgres_upgradesCheck, schedule, roll back and clean up upgrades
GET / POST / DELETE/api/applications/:id/database_forksForks (source is live or backup, optional mask_sql)
GET / PATCH/api/applications/:id/redisShared or dedicated Redis, memory limit and policy

Backups, restores and consoles are covered in Databases and backups.