All research
Field Note 21InfrastructureExperiment · 4 Nov 2026

Testing dedicated PostgreSQL HA for an AI control plane

A D2 PostgreSQL HA comparison in South Africa North: authenticated concurrency, ledger correctness, forced failover and independent recovery checks.

Conceptual blue glass database pair connected across separate platforms, with a recovery archive behind.
33.2 sLongest acknowledgement gap in one forced-failover probe
Exploratory benchmark

First-party engineering evidence. Results apply to the tested configuration and sample; they are not an SLA or a general model ranking.

THE TAKEAWAY

Test the application path, then test the failure path.

Why the database gets its own host

A control plane stores more than login sessions. API keys, spending reservations, queue leases and GPU lifecycle counters all need to survive a database move together. We evaluated a dedicated managed pair while leaving inference hosts and their cost controls separate.

The local database avoids a network hop. The managed database supplies a separate compute budget and a standby in another availability zone. Neither arrangement is automatically faster for every request.

Concurrency changes the comparison

There were no errors in the 6,960 measured combined-path requests. At 16 simultaneous requests, local p95 ranged from 144.8 to 150.6 ms; the managed pair ranged from 132.0 to 136.8 ms. These are individual-run percentiles, not a percentile pooled across all runs.

The worst managed peak repeat was 7.4% below the median local peak result, passing our proposed peak-regression gate. At concurrency one the managed path was slower, consistent with additional database round trips. The table reports the median of the three run-level p95 values.

Failover and recovery are different tests

All 1,096 acknowledged synthetic writes remained present after forced failover. We observed eleven connection errors, one idle-connection event and a longest gap of 33.184 seconds between acknowledgements. The probe retried only idempotent inserts. This does not justify blindly retrying ambiguous application writes.

Azure needed additional time to reconstruct the standby; we waited for healthy HA before repeating load tests. A separate point-in-time restore matched logical backups of both databases, including sequence state. The temporary restore server was removed after verification.

What the experiment does not prove

The application host reached approximately 149 combined control requests per second in the managed peak runs. This is a short synthetic result, not a guaranteed sustained capacity or a count of concurrent model generations. The application host itself is still a separate availability boundary.

Available one-minute database metrics peaked around 24.6% CPU, 18.2% memory and 23 connections in the recorded observation window. The dataset was approximately 19 MB including database overhead; larger data, longer bursts and different write patterns still need testing.

Cost and operational discipline

Our selected regional compute and storage estimate is $362.43 per 730-hour month for the primary, standby and 128 GiB aggregate storage. Additional backup overage, peering traffic, monitoring and taxes are excluded. Credits do not change the underlying price.

The implementation uses verified TLS, separate runtime roles, private networking, a scoped alert budget and existing GPU controls. Database HA does not by itself provide application HA, cross-region disaster recovery or regulatory acceptance.

Failures retained in the record

Initial setup exposed missing test dependencies, a runtime-versus-checkout mismatch, a recovery-helper connection-selection bug and a network deployment race. Corrected runs used isolated databases and the live console source with the reviewed database patch. These setup failures are retained in the engineering record rather than counted as successful benchmark samples.

The first cutover attempt uncovered an Azure public-schema ownership difference. It rolled back before activating target writers. The correction gives the dedicated non-login migration owner permission to create restored objects; application users remain restricted to data operations. The corrected owner-role restore passed a separate rehearsal before the successful retry.

After the gates passed

We moved the two Labs control-plane databases to the dedicated pair on 4 November 2026. Frozen source and target fingerprints matched, runtime-role isolation passed, and a new logical backup from the managed database passed a restore check.

Live validation subsequently completed a GPU-backed queued chat through the console, confirmed duplicate enqueue did not create a second job, checked its usage receipt and revoked the test keys. Inference stayed on its separate hosts, and existing GPU cost controls remained intact.

THE MEASUREMENTS

Results, in context.

Combined control-plane HTTP comparison
Scroll sideways to compare all columns →
Concurrent requestsLocal p95, median runHA p95, median runLocal req/s, median runHA req/s, median run
122.0 ms25.7 ms62.948.1
458.9 ms52.5 ms89.695.9
8109.2 ms97.1 ms106.8120.5
16147.8 ms132.3 ms129.2149.6

Three runs per target. 40 measured requests per concurrent client per run, following five warm-ups per level. All measured requests returned successfully.

TEST SETUP

How we ran it.

  1. PostgreSQL 16 on a B2s_v2 application host versus a private D2ds_v5 managed primary with a matching zone-redundant standby, in South Africa North. The primary has 2 vCPU and 8 GiB RAM; each database copy has 64 GiB storage.
  2. Three rounds per target, ordered local/HA/HA/local/local/HA. Authenticated console-state requests ran at concurrency 1, 4, 8 and 16, with 40 requests per client and five warm-ups per level: 3,480 measured requests per target.
  3. The combined fixture used real PostgreSQL console, key and ledger storage. Model inference, email and external effects were mocked. Timing covers HTTP request through complete response on the application host, not internet latency or model generation.
  4. Each round passed 155 functional assertions, including OTP, software WebAuthn, isolation, spend controls and warm-ups. A separate ten-test PostgreSQL ledger, queue and admission suite passed in each round.
  5. A separate idempotent-write probe ran through forced failover. Independent logical restores were compared with a point-in-time restore using table and sequence fingerprints.
WHAT THIS DOES NOT PROVE

The limits matter.

  • One region, one small dataset and three short repetitions per configuration; a burstable application host ran both the client and local baseline.
  • Synthetic authentication identities and a software WebAuthn authenticator; no claim about users’ physical devices, email delivery or model output quality.
  • No live model inference in the load run. PostgreSQL queue correctness is covered by integration tests, not sustained media-generation traffic.
  • The write-probe recovery gap is not a full-platform RTO, SLA or cross-region DR guarantee.
  • No customer data, credentials, operational resource identifiers or private logs are included in this article.
OPEN FINDINGS

Evidence & sources.

The public extract contains the methods, selected results and caveats in this note. It is a curated summary, not the full raw run. Fingerprints identify the retained source artifacts; gated audio and private operational records are not included.

Download results extract
Source artifact fingerprints · SHA-256
README.md8e89211efa6d28ec42a37ff29dc57aef4cf3bdc771dbabbefd48c58dacb4cae4
combined-control-plane.json0364e43a723755f7573f5822505b93e930a113a04e622d5e2338c7c28fe6f9cb
auth-only.json8f72b717ae64df0ebec58be74ca8cb8c894ec0ca57dab9c6f2938a8e577b28b9
failover.json59ba3ea909dc662314ad13e847f6799e9da6911682317bec71ecca0d2bd2346e
recovery.jsonf0afa4efae3fddaa08948cbfdea1eec6ae78ea6e332e203e36669d5b7533d93b
resource-metrics.json70a72ea358c206479d294c302a291ce0ef7353871ae08494826471187256f7ea

Suggested citation: Embiro Labs Research. “Testing dedicated PostgreSQL HA for an AI control plane” Published 4 Nov 2026. embiro.ai/research/dedicated-postgres-ha

Report a correction