Skip to content

Several processes on one database

By default there is one process. To survive a crash or serve more reads, run several against one Postgres database (a SQLite file can also be shared by a primary and standbys on one machine):

Role What it does
primary The one process that writes. It holds a lease on the database and refuses to start while another primary has it.
standby (--standby) Waits for the lease and starts serving the moment the primary is gone.
replica Serves reads from what the primary has published and sends everything it cannot do (writes, $export, $install) to --primary-url.
Terminal window
refhir --postgres $URL # primary
refhir --postgres $URL --standby # takes over
refhir --postgres $URL --role replica --primary-url http://primary:8080 # reads
  • Writer lease. The primary holds a lease on the database (a Postgres advisory lock, or a file lock <db>.lock for SQLite). If it loses the lease the process exits, and a paused primary that wakes up after a standby took over is fenced off and exits instead of writing.
  • Load balancers. GET /healthz is 200 when a process can take traffic and 503 when it cannot: a standby, a process still starting, or a replica that has stopped following the primary. ?verbose=1 adds connection pool and commit timing counters.
  • Reading your own writes. Write responses carry X-Refhir-Commit-Ts (reads carry the snapshot they ran at). Send the largest value you have seen as X-Refhir-Min-Ts and a replica waits briefly for its snapshot to reach it, then asks the primary. A replica that has no --primary-url to ask answers 503 with Retry-After: 1 instead of an older snapshot. The Go and TypeScript clients do this on their own.
  • /sync works on a replica: queries are answered and invalidated locally; mutations go to the primary on a connection of their own. $websocket subscriptions, Subscription delivery and $export live on the primary.
  • SMART. Tokens, clients and the signing key are in the database, so any process accepts a token another issued. Every process must be given the same --smart-dcr-token and --smart-confidential-secret; standbys and replicas refuse to start without them.

Running it: deploy/cluster (Docker Compose with HAProxy) and the Helm chart’s cluster.enabled.