How it scales

Two numbers matter for an ingest pipeline: what the database can absorb, and what one process can push into it. We've measured both.

MeasurementResultEvidence
Postgres ceiling 4,159 write transactions/s; 31,481 alert-list reads/s — benchmarked on a dedicated 16-vCPU test host. pgbench baseline, September 2026
Single-process ingest 400 alerts/s sustained for 60 s on one process — 24,000/24,000 accepted, zero dropped. Measured on deliberately modest hardware: a shared 8-vCPU dev VM running 2013-era Xeons. Production silo hosts are newer and dedicated to you. ingest drill, September 13, 2026
Burst absorb (1,000 alerts/s) 94,000+ alerts absorbed in one drill window across three app processes backed by a tuned PostgreSQL 16. Horizontal scale is the burst story. ingest drill, September 13, 2026
Vertical resize Rehearsal in progress. Targets under test: ~22 s hypervisor resize, ~75 s end-to-end including service recovery. scheduled — results publish when dated
Per-customer silos Dedicated host + dedicated Postgres per customer, sized for your burst — no noisy neighbors by construction. Silo SKUs, provisioned by one command
flowchart LR
  subgraph GEN["load generators - separate processes, token-bucket paced"]
    L1["loadgen 1"]
    L2["loadgen 2"]
    L3["loadgen N"]
  end
  subgraph APP["app tier - stateless opspingd processes"]
    P1["opspingd 1"]
    P2["opspingd 2"]
    P3["opspingd 3"]
  end
  RL["rate limiter
atomic counters in Postgres"] PG[("PostgreSQL 16
measured ceiling:
4,159 write tx/s
31,481 alert-list reads/s")] L1 --> P1 L2 --> P2 L3 --> P3 P1 --> RL P2 --> RL P3 --> RL RL --> PG

Fig 1 — The ingest path. The app tier holds no shared state, so burst capacity scales by adding processes; the only choke point is Postgres, benchmarked separately (pgbench, September 2026).

flowchart TB
  subgraph ONE["one loadgen process"]
    TB["token bucket paced
at the target rate"] --> WG["concurrent workers"] WG --> ST["local stats:
accepted / dropped / latency"] end ST --> MERGE["merge across processes:
summed throughput, pooled latencies"] MERGE --> PUB["published numbers -
the server is the bottleneck,
never the load generator"]

Fig 2 — Methodology. Load is paced at the target rate rather than slammed; when one generator process saturates, we add generator processes instead of distorting the measurement.

Rate limiting protects the pipeline from abuse, and the ingest cap is deliberately generous — see the API reference for the exact behavior.

flowchart TB
  IN["incoming alerts per second"] --> Q{"Within capacity?"}
  Q -- "yes" --> ACK["202 accepted
drill: 24,000 of 24,000
zero dropped"] Q -- "over the ingest cap" --> REJ["429 - loud, explicit
rejection, retryable"] PGDOWN["Postgres unreachable"] --> ERR["5xx back to the sender
never a silent 202"]

Fig 3 — Failure posture under load: overload and infra failure degrade to explicit errors a sender can retry. The pipeline never queues silently and never acknowledges a write it failed to commit.

How it survives failure

Backups you've never restored are hopes, not backups. So we drill.

ScenarioBehaviorEvidence
Postgres killed mid-load Loud failure — no silent data acceptance (every failed write returns an error to the sender). Crash recovery replays the write-ahead log; zero acknowledged-write data loss. Kill-rehearsal results publish when dated. rehearsal scheduled
Provider outage mid-notification Failed channel sends retry with backoff (1 / 5 / 15 min) from a durable queue; anything still undeliverable dead-letters with an audit entry — it never just vanishes. P1 pushes additionally re-fire until acknowledged. delivery worker, shipped September 13, 2026
Restore from backup Prod database dumped, shipped off-box, and restored into a throwaway PostgreSQL 16: 1.26 s restore, verified row-for-row — every table identical to the source. restore drill, September 13, 2026
Backups Nightly encrypted dump on-host + an off-box encrypted copy. documented procedure
RPO / RTO RPO ≤ 24 h today (≤ 5 min once managed Postgres lands — evaluation open); RTO target 45–75 min. disaster-recovery plan

The public status page is generated live from the API; an unreachable status page is treated as a signal in itself.

How your alerts stay private

The status page can't be silenced by an outage — it runs on infrastructure fully independent of the app, probes the API from outside our stack, and carries operator updates even if everything else is unreachable.

Full control list: security overview and the security questionnaire (also available on request as a document). Data-protection terms: DPA · subprocessor list.

Your data is yours

Full JSON export of your data — profile, alerts, notification rules, channels — is built in: one authenticated call (GET /v2/export), no support ticket. If you leave, your data leaves with you. API reference.

What we won't claim yet

This section is mandatory and stays current. If it ever disappears, treat the rest of this page as marketing.

Commercial

Invoicing with wire/ACH, purchase-order support, and NET 30 on annual contracts. No credit-card-only trap. Request a quote — include your ingest volume and team count and you'll get a concrete number, not a sales call.

A formal SLA document is in progress; until it's signed, the honest commitment is the one this page makes — measured performance, drilled recovery, and a founder's phone number that answers.

Who we are

OpsPing is built by LTFI Tech, LLC (Massachusetts). People ask what LTFI stands for: Learn. Try. Fix. Improve. — the discipline behind everything we ship. About · Contact.

Every figure on this page carries its measurement date. Raw drill logs available on request to prospective enterprise customers — ask via contact. Page last reviewed: 2026-09-13.