incident triage · sev-2 in 64 seconds

Forty-one alerts fired at 02:14, Ruby had the cause by 02:15.

On-call copilot for teams whose pager is louder than their signal. Ruby correlates alerts, deploys and config changes into one confirmed cause, then drafts the rollback while the incident is still open.

Start triagingWatch a 3-min incident

No card. Three services free, permanently.

ruby · halyard / production
refreshed 26 s ago
SEV-2rollback verifyingopen 6m 41s
alerts41 · 9 min
checkout-api02:14:07

p99 latency 2,412 ms > 800 ms for 120 s

pool-router02:14:11

pg connections held 187 / 200

notify-fanout02:14:26

queue depth 3,204 > 1,000

ledger-writer02:14:38

write retries 1,190 in 60 s

edge-cache02:14:52

origin 5xx ratio 4.1%

+ 36 held by Ruby
confirmed cause94% · 3 signals
2,412 msp99 checkout, was 218 ms
41 → 1alerts to causes

Deploy 8f2c1a4 raised POOL_MAX_CONSUMERS in pool-router from 24 to 96, so two replicas held 187 of the 200 connections Postgres allows.

800 ms slo
02:0002:0502:1002:1502:20
deploy 8f2c1a4 · 02:11:30rollback done · 02:16:44
  • deploy 8f2c1a4 landed 41 m before the first alert
  • pg_stat_activity rose 24 -> 187 across the same 90 s window
  • same signature as INC-3902 on 14 Mar 2026, resolved by rollback
blast radius4 of 31 svc
  • checkout-api12,847

    origin

  • notify-fanout3,204

    queued, not lost

  • ledger-writer1,190

    retried to completion

  • edge-cache0

    insulated by stale-while-revalidate

12,847 requests affected · 431 checkouts failed · EUR 18,240 at risk

measured

Ruby triaged 1,204 incidents in the last 30 days, and collapsed 8,913 alerts to get there.

1,204
incidents triaged

last 30 days, 87 teams

47.2%
median MTTR reduction

against each team's own 90-day baseline

8,913
alerts collapsed

into 1,204 causes · 7.4 : 1

1m 04s
to first confirmed cause

median · was 11m 20s

halyard · pager · 22 jul 2026 utc80 alerts → 8 causes
00
01
4102
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Hour 02 is INC-4127. It broke the scale at 41 alerts in nine minutes and still came back as one cause.

one tick
one alert that fired
one node
one cause Ruby confirmed
quiet streak
14 days, ended 22 Jul
on call with ruby
  • Halyard
  • Northwind Freight
  • Basalt Labs
  • Kestrel Health
  • Loam
  • Vantive Systems
capabilities

What Ruby does between the page and the fix.

Four things, all of them from INC-4127 as it actually happened at Halyard on 22 July.

It reads the deploy that broke it

Ruby diffs every change that landed inside the correlation window and points at the line, not the pull request. Here it read a pool ceiling and knew what the database allows.

services/pool-router/config/pool.ts
GitHub logo
LSLennert Smit committed 41 m before the first alert · 02:11:30

Postgres max_connections is 200. Each replica opens two pools, so 96 consumers across two replicas requests 192. Nothing in review expresses that product, which is why this passed.

17 export const POOL = {
18 name: "pg-primary",
19- POOL_MAX_CONSUMERS: 24,
19+ POOL_MAX_CONSUMERS: 96,
20 idleTimeoutMs: 30_000,
21 } satisfies PoolConfig

It runs the rollback, once you say so

Proposed steps, your approval, then execution with a hold-time check on the end. Nothing runs unapproved and every step is logged with its timestamp.

Runbook · pool-router rollback

Ruby proposed this, Amina Bello approved it at 02:15:58. Nothing runs unapproved.

  • 1. Scale POOL_MAX_CONSUMERS back to 24

    02:16:02
  • 2. Drain pool-router replicas 2 / 2

    02:16:44
  • 3. Verify p99 under 400 ms for 120 s

    holding 68 s of 120 s

It wires the symptom to the change

Ruby drew this line: a latency breach in Datadog against a merge in GitHub, 41 minutes apart, across 31 connected sources.

correlation31 sources scanned
Datadog logop99 · checkout-api2,412 ms
breached 800 ms slo at 02:12:00
correlated · 41 m apart
GitHub logo8f2c1a4 · pool-routerdeploy
POOL_MAX_CONSUMERS 24 → 96Lennert Smit · merged 02:11:30

It holds back the 36 alerts you did not need

Every hold states its reason and every one is reversible. Amina saw five alerts that night instead of forty-one, and the ledger says exactly which thirty-six were kept and why.

ruby · suppression ledger
every hold reversible
36held back
5surfaced to Amina
  • ×9checkout-api · 5xx ratio
  • ×7notify-fanout · queue depth
  • ×6ledger-writer · write retries
  • ×5edge-cache · origin 5xx
  • ×5synthetic checkout · timeout
  • ×4pool-router · restart loop
how it triages

Two things nobody wants to do at 02:14, already done when you get there.

postmortem drafts

The write-up starts at 02:15, not on Thursday afternoon.

Ruby fills the sections it can prove from the incident record: summary, timeline, impact, root cause. It writes prose, with the numbers in it, and it cites the deploy.

What it cannot know it leaves to you and says so. Contributing factors and action items came back marked for a human, because judgement is not in the telemetry.

pre-filled
78% of sections, 4 of 6
drafted at
02:15:24, one minute in
cites
8f2c1a4, INC-3902, pg_stat_activity
Postmortem · INC-4127
78% pre-filled
sections
  • Summary
  • Timeline
  • Impact
  • Root cause
  • Contributing factorsyou
  • Action itemsyou
root cause · auto-drafted 02:15:24

At 02:11:30 UTC on 22 Jul 2026, deploy 8f2c1a4 raised POOL_MAX_CONSUMERS in pool-router from 24 to 96.

Each replica opens two pools, so the two running replicas requested 192 of the 200 connections Postgres allows; 187 were held at the moment checkout-api began timing out.

p99 checkout latency moved from 218 ms to 2,412 ms over 90 seconds and 431 checkouts failed before the rollback completed at 02:16:44.

The change passed review because the pool ceiling is not expressed anywhere near the database's connection limit, and no test asserts the product of replicas, pools and consumers.

2 inputs still need you· reviewers: Amina Bello, Lennert Smit
ruby · ask

p99 by route for checkout-api since the deploy

generated promqlran in 340 ms over 4.1 M samples
histogram_quantile(0.99, sum by (route, le) (rate(http_request_duration_seconds_bucket{service="checkout-api"}[2m])))
routep99change
  • POST /v2/checkout/confirm2,412 ms+1,006%
  • POST /v2/checkout/session1,884 ms+742%
  • GET /v2/checkout/:id604 ms+178%
  • GET /v2/health18 ms+2%
ask in prose

Ask the question you would have asked a colleague, get the query and the rows.

Ruby knows which route labels your histograms carry and which service owns them, so a sentence becomes PromQL you can read, edit and keep.

It shows the query it wrote. If it guessed a label wrong you will see that before you trust the number, which is the only way this is useful at two in the morning.

answered in
340 ms over 4.1 M samples
query languages
PromQL, LogQL, SQL, Datadog
saved by halyard
62 asks kept as dashboards
sources

It reads what you already run.

Ruby correlates across 31 sources and writes back to 4 of them. Read access is enough to start; write-back is opt-in per target.

Not on the list? OpenTelemetry ingest and raw webhooks cover anything that can emit an event with a timestamp.

  • Datadog logo
    Datadogreads monitors + metrics
  • Sentry logo
    Sentryreads issues + releases
  • PagerDuty logo
    PagerDutyreads pages, writes notes
  • GitHub logo
    GitHubreads deploys + diffs
  • Grafana logo
    Grafanareads dashboards
  • Kubernetes logo
    Kubernetesreads events + rollouts
  • Linear logo
    Linearwrites action items
  • Slack logo
    Slackwrites incident threads
31 sources4 write-back targetsmedian connect time 4 min
pricing

Priced per engineer, never per alert. A loud night should not cost more.

Starter

EUR 0

for 3 services

Enough to watch one critical path.

  • Up to 3 services
  • 7-day incident history
  • 6 sources
  • 1 write-back target
  • Correlation + confirmed cause

Team

most rotations
EUR 38

per engineer / month

What on-call rotations of 4 to 40 actually run.

  • Unlimited services
  • 18-month incident history
  • All 31 sources · 4 write-back targets
  • Runbook execution with approval gates
  • Postmortem drafts, 78% pre-filled on average
  • Blast radius + suppression ledger

Scale

Talk to us

annual, from EUR 24k

For fleets where the collectors cannot leave your VPC.

  • Everything in Team
  • Self-hosted collectors
  • SSO + SCIM, SOC 2 Type II report
  • 99.95% SLA, 15-minute response
  • Audit export to your warehouse

Billed on engineers in the rotation, not seats in the workspace. Halyard runs 9 engineers on Team and pays EUR 342 a month.

Your next page lands at 02:14. Ruby will already be reading it.

Three services free. Median time from connecting Datadog to a first correlated cause is 4 minutes.