How the copy stays fresh
The core ledger runs on managed Postgres. Inside me-central-1 we replicate
synchronously across zones: a write is not acknowledged to the application until a second
zone has it. Across regions we replicate asynchronously, streaming
write-ahead log records to Frankfurt as fast as the link allows and never blocking a
customer's payment on a packet crossing a continent.
That choice is the whole trade-off. Asynchronous means the Frankfurt copy is always
slightly behind, and in a hard failure of the primary we would lose whatever had not yet
shipped. So we measure the lag obsessively. Over the last ninety days the median has been
1.4 seconds and the 99th percentile 8.6 seconds, with a single excursion to 71 seconds
during a provider network event in February that resolved itself before anyone reached a
laptop. Our alarm fires at 45 seconds sustained for two minutes, which pages the platform
on-call.
Roughly, the cluster definition looks like this. Real one has more tags and a lot more
opinions about parameter groups.
-- platform/datastore/yusr-core.yaml
cluster: yusr-core
engine: postgres 15.6
primary:
region: me-central-1 # Riyadh
zones: [me-central-1a, me-central-1b, me-central-1c]
replication:
in_region: synchronous # quorum: 2 of 3 zones must ack
encryption:
at_rest: kms/yusr-core-primary # key material stays in me-central-1
backup:
continuous_wal: true
snapshot_every: 15m
retention_days: 35
standby:
region: eu-central-1 # Frankfurt
replication:
cross_region: asynchronous # never in the write quorum
stream: wal
promotion:
mode: manual
approvals: 2 # platform on-call + incident commander
encryption:
at_rest: kms/yusr-core-dr
alarm:
replica_lag_seconds: 45
for: 2m
page: platform-oncall
objectives:
rpo: 15m
rto: 45m
The fifteen-minute RPO is not derived from the replication lag — that would be optimistic
to the point of dishonesty. It comes from the snapshot interval, which is the floor we can
actually defend if streaming replication itself is what broke. If everything is healthy we
expect to lose seconds. Fifteen minutes is the number we are willing to write down.
What we promise, per component
Not everything deserves the same effort. A missing statement PDF for four hours is
annoying; a ledger that cannot say what your balance is for four hours is a different
category of problem. So the targets are set per component and reviewed by the risk
committee each half.
RTO is measured from the incident commander's decision to fail over,
not from the start of the incident. Detection and the argument about whether to pull the
handle are separately budgeted at 15 minutes.