DB Olympics

Queries · q337 · VP Platform Engineering · week 2, night 1

Carts.remind Failure Root Cause: Error Messages

“Did the 20 carts.remind failures in Nov 2025 share a common root cause (pointing to one shared bug/config issue) or look like scattered, tenant-specific problems (pointing to load/capacity)?”

Manager · asked the questionDiego MoralesVP Platform Engineering. Former reliability lead at a payments company. Owns uptime and the integrations merchants depend on.
Analyst · planned the reportLucas MoreauPragmatic: answers the question asked with the simplest reliable report.
Engineer · wrote the SQLOmarPragmatic: the shortest correct query, aggregates first and joins dimensions afterwards, FILTER clauses for conditional counts.

Fictional people at a fictional company, each played by a language-model agent. Who they are and what they are told

  1. A business event lands on the VP Platform Engineering's desk

    Week 1; shared with Samuel Whitcombe, Head of Merchant Success

    Leadership wants a review of platform reliability in 2025: failed and slow background jobs, health check failures, rate limiting, webhook delivery problems, and which merchants felt them.

  2. Diego Morales writes to Lucas Moreau

    The manager, at the start of week 2

    Subject: Re: 2025 Platform Reliability Review — good start, a few things I need tightened up

    Lucas,

    Thanks — this is useful and more honest than I expected on the limits of what we can see. A few things stood out and need more work before Friday's memo goes to leadership.

    First, the retention gap is itself a finding, not just a caveat. We're flying with 90 days of job history and 60 days of health-check history — that means we genuinely don't know how 2025 looked before October. I want that stated plainly and separately in the memo as a reliability/observability gap in its own right, not buried as a footnote under the carts.remind story.

    Second, the ERP/WMS/Accounting webhook stuck-retry pattern is, to me, the most important and actionable thing in here — more than the one-week carts.remind incident. I want that properly validated and sized, not eyeballed, before we say anything about it to leadership.

    Questions for this week:

    1. Can you redo the webhook comparison correctly and tell me: how many merchants are affected by this stuck-retry pattern, and what's the revenue or order volume behind them? I want to know if this is a handful of our biggest accounts or a long tail.
    2. Has the ~15% stuck-retry rate on those sync webhooks been happening all year, or is it new/recent? Even without full job history, is there any way to tell whether this is a longstanding bug we've lived with or something that regressed recently?
    3. On carts.remind — you said it looks tied to a feature flag or config rather than load. Can we get more confidence on that? I want to know if this is a one-off we already fixed, or a latent risk that could recur with other job types.
    4. Setting aside strict proof of causation, can you give me your best read on whether the ticket-volume climb for the 10 affected tenants in the weeks before the failures showed up in our logs is something merchants were telling us about directly (i.e., check if their tickets mention sync/reminders/missing carts) — even a rough read would tell us if our support channel was effectively an early warning system we ignored.

    On rate limiting: agreed, drop it for this cycle — don't spend a slot trying to force an answer out of config data alone. Just flag it as a 2026 instrumentation ask, as you already have.

    Priority for your remaining slots: #1 and #2 above. The webhook/sync issue is the one I can take into a fix-it conversation with engineering next week if the numbers hold up — I'd rather have that nailed down than more polish on the carts.remind narrative.

    Diego

  3. Lucas Moreau plans the night

    The analyst · week 2, night 1, request 3 of 3

    Diego wants the webhook stuck-retry finding properly validated before it goes to leadership, and that's explicitly his #1 and #2 priority this week, so two of tonight's three slots go there: first, a correct tenant-level view (fixing last week's broken join) showing exactly how many merchants have ERP/WMS/Accounting sync webhooks stuck above a real threshold and what revenue/order volume sits behind them, so we can say concentrated-in-big-accounts vs long-tail; second, a full-year monthly trend of that same stuck-rate (webhook_deliveries has clean 12-month coverage, unlike job_runs/health_checks) to tell if this is longstanding or a recent regression. I'm using my third slot on Diego's #3 (carts.remind confidence) since it's a cheap, high-value pull: the actual error_message on the 20 failed runs will tell us in one query whether this was one shared root cause (supports his 'latent risk that could recur' concern being containable) or scattered causes (supports a load/capacity read). I'm deferring Diego's #4 (checking if tickets from the 10 affected tenants actually mention sync/reminders/carts) to night 2 since it needs careful text-search scoping and isn't his top priority this week.

    Carts.remind Failure Root Cause: Error Messages
    Question
    Did the 20 carts.remind failures in Nov 2025 share a common root cause (pointing to one shared bug/config issue) or look like scattered, tenant-specific problems (pointing to load/capacity)?
    One row per
    failed carts.remind job run (20 rows expected)
    Columns
    • tenant_name
    • queued_at
    • started_at
    • finished_at
    • error_message
    • attempt
  4. Omar writes the SQL

    The engineer · 1 dry run on the empty schema, then the submission

    Dry run 1 · STATUS: COMPILES (dry run on the empty schema, no data read)
    select
      t.name as tenant_name,
      jr.queued_at,
      jr.started_at,
      jr.finished_at,
      jr.error_message,
      jr.attempt
    from job_runs jr
    join jobs j on j.id = jr.job_id
    join tenants t on t.id = jr.tenant_id
    where j.handler = 'carts.remind'
      and jr.status = 'failed'
      and jr.queued_at >= date '2025-11-01'
      and jr.queued_at < date '2025-12-01'
    order by jr.queued_at asc, t.name asc

    “Query compiles cleanly against the schema.”

    Submitted · the SQL of the last dry run, unchanged · Submitted to tonight's batch. Your work on this request is done.

    “Submitted. The report returns one row per failed carts.remind run in November 2025 (tenant name, queued/started/finished timestamps, full error message, and attempt number), ordered by queue time then tenant — ready for Lucas to eyeball whether the error strings cluster around one cause or scatter across tenants.”

  5. The report comes back overnight

    As Lucas Moreau saw it, from the small dataset the agents worked on

    tenant_name            | queued_at               | started_at              | finished_at             | error_message                           | attempt
    -----------------------+-------------------------+-------------------------+-------------------------+-----------------------------------------+--------
    Gratlinie Outdoor      | 2025-11-28 14:40:04.027 | 2025-11-28 14:40:05.004 | 2025-11-28 14:40:06.074 | 503 Service Unavailable: storefront API |       3
    Marrowby & Vane        | 2025-11-28 14:40:05.741 | 2025-11-28 14:40:10.093 | 2025-11-28 14:40:12.292 | 503 Service Unavailable: storefront API |       3
    Cinder Peak Sports Co. | 2025-11-28 14:40:06.352 | 2025-11-28 14:40:06.776 | 2025-11-28 14:40:08.558 | 503 Service Unavailable: storefront API |       3
    Petalcourt Beauty      | 2025-11-28 14:40:06.878 | 2025-11-28 14:40:08.079 | 2025-11-28 14:40:09.171 | 503 Service Unavailable: storefront API |       3
    Brennquell Kaffee      | 2025-11-28 14:40:06.939 | 2025-11-28 14:40:07.282 | 2025-11-28 14:40:08.716 | 503 Service Unavailable: storefront API |       3
    Kibblewick             | 2025-11-28 14:40:07.143 | 2025-11-28 14:40:07.534 | 2025-11-28 14:40:08.362 | 503 Service Unavailable: storefront API |       3
    Fennel & Flint         | 2025-11-28 14:40:08.753 | 2025-11-28 14:40:12.312 | 2025-11-28 14:40:13.509 | 503 Service Unavailable: storefront API |       3
    Studio Vrij            | 2025-11-28 14:40:09.151 | 2025-11-28 14:40:12.35  | 2025-11-28 14:40:14.566 | 503 Service Unavailable: storefront API |       3
    Ampfeld Elektronik     | 2025-11-28 14:40:09.362 | 2025-11-28 14:40:11.517 | 2025-11-28 14:40:12.429 | 503 Service Unavailable: storefront API |       3
    Cragsley Outfitters    | 2025-11-28 14:40:09.758 | 2025-11-28 14:40:11.022 | 2025-11-28 14:40:13.348 | 503 Service Unavailable: storefront API |       3
    Gratlinie Outdoor      | 2025-11-28 15:40:03.673 | 2025-11-28 15:40:06.151 | 2025-11-28 15:40:07.4   | 503 Service Unavailable: storefront API |       3
    Kibblewick             | 2025-11-28 15:40:05.175 | 2025-11-28 15:40:07.89  | 2025-11-28 15:40:11.728 | 503 Service Unavailable: storefront API |       3
    Cragsley Outfitters    | 2025-11-28 15:40:05.504 | 2025-11-28 15:40:06.246 | 2025-11-28 15:40:09.483 | 503 Service Unavailable: storefront API |       3
    Fennel & Flint         | 2025-11-28 15:40:05.605 | 2025-11-28 15:40:10.525 | 2025-11-28 15:40:11.663 | 503 Service Unavailable: storefront API |       3
    Studio Vrij            | 2025-11-28 15:40:05.75  | 2025-11-28 15:40:06.179 | 2025-11-28 15:40:07.151 | 503 Service Unavailable: storefront API |       3
    Ampfeld Elektronik     | 2025-11-28 15:40:05.814 | 2025-11-28 15:40:06.925 | 2025-11-28 15:40:08.173 | 503 Service Unavailable: storefront API |       3
    Marrowby & Vane        | 2025-11-28 15:40:06.447 | 2025-11-28 15:40:10.262 | 2025-11-28 15:40:11.83  | 503 Service Unavailable: storefront API |       3
    Cinder Peak Sports Co. | 2025-11-28 15:40:07.655 | 2025-11-28 15:40:08.369 | 2025-11-28 15:40:09.655 | 503 Service Unavailable: storefront API |       3
    Petalcourt Beauty      | 2025-11-28 15:40:09.473 | 2025-11-28 15:40:14.407 | 2025-11-28 15:40:15.307 | 503 Service Unavailable: storefront API |       3
    Brennquell Kaffee      | 2025-11-28 15:40:10.038 | 2025-11-28 15:40:11.938 | 2025-11-28 15:40:15.191 | 503 Service Unavailable: storefront API |       3
    (20 rows)
  6. What came of it

    The memo and the queries that followed; links found by title, so inferred

    Later queries that build on this report:

    It builds on:

  7. It becomes benchmark query q337

    Changed only where the benchmark needs the same result on every system

    • determinismtie-breaker: job_runs primary key
    • made explicita selected t.col gets AS col, its standard name made explicit (5×)
    • determinismthe standard leaves the place of NULLs in a sort to the implementation: NULLS LAST ascending, NULLS FIRST descending, as in the reference results (3×)
    The benchmark text, against the submitted SQL
    select  t.name as tenant_name,  jr.queued_at,  jr.started_at,  jr.finished_at,  jr.error_message,  jr.attempt  jr.queued_at AS queued_at,  jr.started_at AS started_at,  jr.finished_at AS finished_at,  jr.error_message AS error_message,  jr.attempt AS attemptfrom job_runs jrjoin jobs j on j.id = jr.job_idjoin tenants t on t.id = jr.tenant_idwhere j.handler = 'carts.remind'  and jr.status = 'failed'  and jr.queued_at >= date '2025-11-01'  and jr.queued_at < date '2025-12-01'order by jr.queued_at asc, t.name ascorder by jr.queued_at asc NULLS LAST, t.name asc NULLS LAST, jr.id asc NULLS LAST
    select
      t.name as tenant_name,
      jr.queued_at AS queued_at,
      jr.started_at AS started_at,
      jr.finished_at AS finished_at,
      jr.error_message AS error_message,
      jr.attempt AS attempt
    from job_runs jr
    join jobs j on j.id = jr.job_id
    join tenants t on t.id = jr.tenant_id
    where j.handler = 'carts.remind'
      and jr.status = 'failed'
      and jr.queued_at >= date '2025-11-01'
      and jr.queued_at < date '2025-12-01'
    order by jr.queued_at asc NULLS LAST, t.name asc NULLS LAST, jr.id asc NULLS LAST
    1 ms10 ms100 msHyper3.2 msDuckDB2.5 msGizmoSQL4.9 msclickhouse_brew33.7 msFirebolt24.4 msDataFusion32.2 msClickHouse11.4 ms
  8. Everything, as recorded

    The agents' own records, as the role play wrote them; only the personal data of the person who ran it is redacted

    Omar's whole session, 7 turns
    • The request, as Omar received it
      Report request from Lucas Moreau (analyst for the VP Platform Engineering):
      
      Title: Carts.remind Failure Root Cause: Error Messages
      Question: Did the 20 carts.remind failures in Nov 2025 share a common root cause (pointing to one shared bug/config issue) or look like scattered, tenant-specific problems (pointing to load/capacity)?
      Grain: one row per failed carts.remind job run (20 rows expected)
      Columns:
      - tenant_name
      - queued_at
      - started_at
      - finished_at
      - error_message
      - attempt
      Details: Table job_runs joined to jobs (handler='carts.remind') and tenants, filtered to status='failed' and queued_at in November 2025 (the same 20 rows identified in last week's handler breakdown). Show the full error_message text and attempt number for each failed run so we can see if they cluster around one error string/cause or vary. Order by queued_at ascending, tie-break tenant_name ascending.
      
      Check your query with the warehouse's dry_run tool, then hand it in with submit.
    • Omar calls dry_run
      select
        t.name as tenant_name,
        jr.queued_at,
        jr.started_at,
        jr.finished_at,
        jr.error_message,
        jr.attempt
      from job_runs jr
      join jobs j on j.id = jr.job_id
      join tenants t on t.id = jr.tenant_id
      where j.handler = 'carts.remind'
        and jr.status = 'failed'
        and jr.queued_at >= date '2025-11-01'
        and jr.queued_at < date '2025-12-01'
      order by jr.queued_at asc, t.name asc
    • The warehouse answers
      STATUS: COMPILES (dry run on the empty schema, no data read)
      COLUMNS: tenant_name, queued_at, started_at, finished_at, error_message, attempt
    • OmarQuery compiles cleanly against the schema.
    • Omar calls submit
      select
        t.name as tenant_name,
        jr.queued_at,
        jr.started_at,
        jr.finished_at,
        jr.error_message,
        jr.attempt
      from job_runs jr
      join jobs j on j.id = jr.job_id
      join tenants t on t.id = jr.tenant_id
      where j.handler = 'carts.remind'
        and jr.status = 'failed'
        and jr.queued_at >= date '2025-11-01'
        and jr.queued_at < date '2025-12-01'
      order by jr.queued_at asc, t.name asc
    • The warehouse answers
      Submitted to tonight's batch. Your work on this request is done.
    • OmarSubmitted. The report returns one row per failed `carts.remind` run in November 2025 (tenant name, queued/started/finished timestamps, full error message, and attempt number), ordered by queue time then tenant — ready for Lucas to eyeball whether the error strings cluster around one cause or scatter across tenants.