NewDiffling now pings you on iMessage

Open the PR.
Diffling handles
the rest.

Diffling is the always-on agent for everything after the pull request. It follows your merge into production, watches every metric, migration and log, and pings you on Slack or iMessage the moment something smells off. Usually with the fix attached.

Currently hatching · free during beta · installs as a GitHub App

You're here · the duck is off duty
Try it: move your cursor off the page, or stop moving it for a few seconds.

Reads from the stack
you already have.

  • GitHub
  • GitLab
  • Vercel
  • AWS
  • Datadog
  • Sentry
  • Grafana
  • PostHog
  • LaunchDarkly
  • Postgres
  • Slack
  • iMessage
  • Linear
  • PagerDuty
A night shift, replayed at 3,600× speed
diffling · night shift6:00 PM
  1. Waiting for a merge…
DifflingiMessage
iMessage

A merge, in four panels.

Everything that happens after you close the laptop. Which, from now on, is not your problem.

Merged. Logging off 👋
feat(checkout): pricing engine v2 #4821
⇄ Mergedjay merged 14 commits into main
Merge pull request
6:02 PM

You merge #4821 and log off like a normal human.

  1. CI312 tests · 4m 11s
  2. Buildprod-7f3a · 2m 02s
  3. Migrate0042_price_tiers · 1.2s
  4. Canary10% → 50% → 100%
  5. Metricsp95 214ms · errors flat
6:14 PM

The duck follows it all the way to prod. Every stage. Every metric.

Ping! Alert sent
2:14 AM

Checkout is 2.6× slower. Everyone's asleep. Except the duck.

8:00
Tuesday · 0 pages overnight
Difflingnow

Overnight: caught a checkout slowdown from #4821, rolled back the flag, fix is in #4822. Coffee first ☕

8:00 AM

You wake up to a fix. Not a fire.

SFX: your phone, staying silentTo be continued… (every deploy)

Everything after git push.

Not crashes — your error tracker already has those. Diffling watches the things nothing alerts on: a backfill that will die halfway, a feature nobody can reach, a cron that quietly stopped.

0043_backfill_order_totalsrunning
4.1M / 6.7M rows11k rows/slock waits: 0
⚠ Will hit statement_timeout at ~5.2M rows. About 1m 40s from now.
Chunk it by 50k? Drafted in #4823− one UPDATE over 6.7M rows+ 134 batches, resumable, 0 long locks

Migrations and backfills

Nothing pages you for a backfill that will die halfway through, or a lock quietly piling up behind it. Diffling reads the plan, tracks the row count against your timeouts, and speaks up before row 4,000,001 times out — with the chunked version already written.

routebeforeafter #4821Δ p95
POST /api/checkout212ms548ms+158%
GET /api/cart88ms91ms+3%
GET /api/search140ms132ms−6%
38 queries/request (was 2) · N+1 in PriceTier.load()

Slower APIs

Did your PR make an existing endpoint slower? Diffling diffs p50/p95/p99 per route, before and after the merge, and finds the query that did it.

$ npm test -- checkout
✕ checkout.spec.ts › applies tier discount
Expected: 90.00
Received: 89.99
✓ 311 passed · 1 failed
Flaky, not broken. Fails 3/40 runs, only after 00:00 UTC. The fixture uses Date.now(). Pinned it in #4830.

CI & flaky tests

Red build at 11pm? It reads the logs, tells flake from failure, then reruns or fixes.

onboarding-v2shipped 3 days ago
0.4%of new users saw it
development100%✓
staging100%✓
production0%✕ ← there it is

Features nobody uses

Shipped it and nobody's touching it? Diffling checks the flag, the targeting, the funnel, and whether the thing even renders.

  • ∅
    200 OK, empty body/api/cart · 1.2% of requests since #4821
  • ↻
    Retry stormpayments-worker · 14 retries/min, usually 0
  • ⏲
    Cron went quietnightly-invoices · last ran 26h ago

Things that just feel off

Not just stack traces. Silent 200s, retry storms, a queue slowly backing up, a cron that quietly stopped running.

lib/money.ts
export function formatPrice(cents) {
  return new Intl.NumberFormat("en-US", {
    style: "currency", currency: "USD",
  }).format(cents / 100)
}
checkout/utils.ts · new in #4821
export const toCurrency = (amt) =>
  new Intl.NumberFormat("en-US", {
    style: "currency", currency: "USD",
  }).format(amt / 100)
94%same

Copy-paste creep

Catches the third copy of formatCurrency() before it becomes the fourth, and points at the one to keep.

Rubber duck debugging, v2

For decades you explained your bugs to a rubber duck. This one explains them back.

Diffling doesn't just say something broke. It says why, where, which PR, and what it already did about it, in plain English. And when it isn't sure, it says that too, with a number on it.

diffling says

Routines, in plain English.

Tell Diffling what “wrong” looks like for your team. A few lines of YAML, with the logic in plain English. It runs on a trigger, a schedule, or a hunch, and figures out the queries itself.

.diffling/routines/adoption-watch.yml
1# .diffling/routines/adoption-watch.yml2name: adoption-watch3description: Catch features that ship but nobody uses.45when:6  event: deployed7  labels: [feature]8  rollout: 100%9  wait: 48h1011check: Are the new code paths actually getting hit?12if: usage is under 1% of eligible users1314then:15  - Verify the feature flag in every environment16  - Check the rollout and targeting rules17  - Look for render errors on the new screens18  - Read the funnel in PostHog1920notify:21  - imessage: jay22  - slack: growth2324allow: [open_pr]25never: [flip_flags]
Preview
When
⚡ 48h after any PR labeled `feature` reaches 100%
Check
Are the new code paths actually getting hit?
If
usage is under 1% of eligible users
Then
  1. Verify the feature flag in every environment
  2. Check the rollout and targeting rules
  3. Look for render errors on the new screens
  4. Read the funnel in PostHog
Notify
jay · iMessage#growth · Slack
Allow / never
open a PRnever flip a flag without asking
Drop the file in .diffling/routines/ and open a PR. Diffling works out the queries, dashboards and logs.

It finds you. At the right volume.

Choose how loud Diffling gets for each kind of problem: a digest, a Slack thread, a DM, an iMessage, or an actual phone call.

BZZT!
Alert level
iMessage

Texts you wherever you are, and says what it already did about it.

Diffling
Checkout p95 is 548ms (normally 212) since #4821. Only EU, only big carts.
I rolled pricing-v2 back to 0% in EU. It's recovering. Fix is drafted in #4822, no need to get up 🌙
🙏

Get your deploys in a row.

Every stage after the merge, checked in order. Speaks up if anything steps out of line.

follow me →
CI ✓
Build ✓
Migrate ✓
Canary ✓
100% ✓
p95 ✓
Errors ✓
Adoption ✓
Dupes ✓
follow me →
CI ✓
Build ✓
Migrate ✓
Canary ✓
100% ✓
p95 ✓
Errors ✓
Adoption ✓
Dupes ✓

Hatches in three steps.

About five minutes. Most of it spent finding your Datadog API key.

01

Install the GitHub App

Pick the repos. Diffling reads PRs, merges and deploys. It never pushes to main.

GitHubGitLab
02

Plug in your telemetry

Point it at the places your truth lives. Read-only tokens, about two minutes.

VercelAWSDatadogSentryGrafanaPostHogPostgres
03

Tell it where you are

Slack, iMessage, email, a phone. Then open a PR and go outside.

SlackiMessageEmailLinearPagerDuty

A very well-behaved duck.

An agent that watches production needs manners. Diffling has them, and you decide exactly how much it's allowed to touch.

Read-only by default

Diffling watches with read-only tokens. Anything that writes either asks first or follows a routine you approved.

Every fix is a PR

Fixes arrive as pull requests with the evidence attached. You review. You merge. The duck waits.

Receipts for everything

Every check, query and message is logged with the reasoning behind it. Audit the duck anytime.

Tells you when it's guessing

Every finding carries a confidence and the evidence behind it. A hunch is labelled a hunch, and a hunch never triggers an action.

Never pushes to main

Not at 2am. Not on a Friday. Not ever. It's a duck, not a cowboy.

Questions, answered.

Still curious? Ask the duck. It's surprisingly patient.

Is this just another error tracker?

No. Error trackers tell you something threw. Diffling tells you your PR made checkout 158% slower for EU users with big carts, why, and what it already did about it. It connects the merge to what happened next.

Does it replace Datadog, Sentry or Grafana?

Nope, it reads from them. Think of it as the teammate who actually looks at all the dashboards after every deploy, and then tells you what it saw in one sentence.

Will it spam me?

It only speaks up when it has something worth saying. You set alert levels per repo, per routine and per hour of the night. Most weeks you'll just get a digest.

Can it fix things on its own?

Only what you allow: flipping a flag back, re-running a flaky job, pausing a backfill, opening a PR. Anything else, it asks first. It never merges and never pushes to main.

What happens when it's wrong?

It will be, sometimes. So every finding ships with a confidence score and the evidence it used, a hunch is labelled as one, and anything below your threshold waits for the digest instead of your phone. Only confirmed findings can trigger an action, and every action is reversible and logged. Mark a call wrong and the routine that produced it gets tightened.

What about my code and data?

Diffling uses read-only tokens, keeps an audit log of everything it touched, and you can revoke access in one click. If that sentence isn't enough, talk to us and we'll show you the plumbing.

Why a duck?

Rubber duck debugging, except this duck finally talks back. Also: calm on the surface, paddling like hell underneath. That's the whole job description.

I've got prod. Go to bed.
all quiet · 14 deploys watched
Private beta, hatching now

Go to sleep.
The duck's got prod.

Open the PR. Close the laptop. Diffling handles the rest, and tells you about it over coffee.

Free during beta · no credit card · leave anytime, the duck won't take it personally