Sardine incident

Prod Australia instance performance degradation (v1/customers API and v1/issuing/risks API)

Resolved after 40 minutes, affecting Issuing API and Customer APIs, on September 27, 2026.

postmortem Sep 29, 2026, 09:43 PM UTC

## Summary On September 27–28, 2026, Sardine experienced two periods of elevated latency and request timeouts in our **Australian production region**. Requests to `/v1/issuing/risks` , `/v1/customers`, and `/v1/feedbacks` were affected from 12:16–22:00 UTC on September 27 and again from 23:20 UTC on September 27 until 00:23 UTC on September 28. A separate high-volume data-processing workload overloaded a shared regional database. An unbounded historical aggregation initially consumed most of the database capacity. As records accumulated, stale database statistics caused another frequently used transaction lookup to select an inefficient query plan. Query timeouts then recycled database connections, repeatedly reintroducing that plan and amplifying the load. The incident affected API availability, transaction persistence, and the risk level evaluation. ## Timeline _All times UTC._ * **September 27, 12:16** — A high-volume data-processing workload begins. Database CPU reaches capacity and `/v1/issuing/risks` timeouts start. * **14:20** — We receive the first customer report. * **14:29** — The primary support on-call acknowledges a page, but the issue is not escalated effectively. * **18:02** — We send the first substantive customer impact update. * **18:05** — The need for engineering escalation is identified. * **21:06** — Sardine declares an incident. * **21:38** — Active engineering investigation and remediation begin. * **22:03** — A database resize and primary switchover restore customer-facing service. * **22:12** — The high-volume workload is paused and database utilization returns to normal. * **22:40** — The first event is marked resolved. * **22:49** — Database CPU monitors are added for all production regions. * **23:20** — The workload resumes and triggers a second degradation. * **23:41** — The new database monitor pages the on-call team and is acknowledged within 13 seconds. * **September 28 00:14** — A second database resize and primary switchover resolve the inefficient transaction lookup. * **00:23** — Optional aggregation work is disabled and the remaining customer-facing timeouts end. * **00:26 onward** — Database statistics are refreshed and an optimized composite index is deployed. ## Root Cause The incident resulted from the interaction of four conditions: 1. **Unbounded aggregation:** A synchronous query scanned the full transaction history for given condition. This consumed most database capacity when the high-volume workload began. 2. **Inefficient transaction lookup:** As new records accumulated, database statistics did not refresh quickly enough. The query planner selected an index that scanned a customer’s growing transaction history rather than performing a targeted lookup. 3. **Connection recycling:** Timed-out queries caused database connections to close. Replacement connections repeatedly began with the same inefficient query plan, creating a feedback loop of expensive scans, timeouts, and reconnects. ## Contributing Factors * Our API monitoring excluded the relevant client-timeout responses, and we did not alert on query cancellations or sustained database-connection churn. Database CPU monitor was only configured for non-pagerduty alert * The customer detected the first event before our monitoring did. Delayed engineering escalation extended the response time. * Our first recovery addressed the immediate pressure but did not prevent the workload from triggering a second event when it resumed. ## Resolution and Recovery For the first event, we resized the database and switched to the new primary, then paused the high-volume workload. For the second event, we again resized and switched the primary, then disabled optional aggregation to remove the remaining load. After service recovery, we: * Refreshed database statistics. * Deployed a composite index that gives both new and established connections an efficient transaction-lookup path. * Added database CPU monitors for every production region. * Removed optional, unused aggregation from the `/v1/customers` path * Kept the Australian production database at a higher baseline capacity while we complete the permanent query fixes and capacity review. ## Corrective Actions We are taking the following actions: ### Database and application resilience * Replace the affected transaction lookup with an atomic, consistently indexed operation. * Skip unnecessary historical aggregation and bound any required fallback query. * Evaluate a read pool so issuing-risk reads do not compete with customer-event writes on the primary. * Review steady-state database capacity after the query fixes are complete. ### Monitoring and response * Expand monitoring for client timeouts and database metrics * Improve incident routing so customer reports, support tickets, and on-call escalation converge quickly.

Started
Sep 27, 2026, 09:56 PM UTC
Resolved
Sep 27, 2026, 10:36 PM UTC
Duration
40m
Detected by Pingoru
Sep 27, 2026, 09:56 PM UTC

Affected components

Issuing APICustomer APIs

Update timeline

  1. investigating Sep 27, 2026, 09:56 PM UTC

    Australia instance (api.au.sardine.ai) is degraded for v1/customers API and v1/issuing/risks API. Team is actively looking into it.

  2. monitoring Sep 27, 2026, 10:21 PM UTC

    A fix has been implemented and we are monitoring the results.

  3. resolved Sep 27, 2026, 10:36 PM UTC

    This incident has been resolved. We'll follow up with post mortem.

  4. postmortem Sep 29, 2026, 09:43 PM UTC

    ## Summary On September 27–28, 2026, Sardine experienced two periods of elevated latency and request timeouts in our **Australian production region**. Requests to `/v1/issuing/risks` , `/v1/customers`, and `/v1/feedbacks` were affected from 12:16–22:00 UTC on September 27 and again from 23:20 UTC on September 27 until 00:23 UTC on September 28. A separate high-volume data-processing workload overloaded a shared regional database. An unbounded historical aggregation initially consumed most of the database capacity. As records accumulated, stale database statistics caused another frequently used transaction lookup to select an inefficient query plan. Query timeouts then recycled database connections, repeatedly reintroducing that plan and amplifying the load. The incident affected API availability, transaction persistence, and the risk level evaluation. ## Timeline _All times UTC._ * **September 27, 12:16** — A high-volume data-processing workload begins. Database CPU reaches capacity and `/v1/issuing/risks` timeouts start. * **14:20** — We receive the first customer report. * **14:29** — The primary support on-call acknowledges a page, but the issue is not escalated effectively. * **18:02** — We send the first substantive customer impact update. * **18:05** — The need for engineering escalation is identified. * **21:06** — Sardine declares an incident. * **21:38** — Active engineering investigation and remediation begin. * **22:03** — A database resize and primary switchover restore customer-facing service. * **22:12** — The high-volume workload is paused and database utilization returns to normal. * **22:40** — The first event is marked resolved. * **22:49** — Database CPU monitors are added for all production regions. * **23:20** — The workload resumes and triggers a second degradation. * **23:41** — The new database monitor pages the on-call team and is acknowledged within 13 seconds. * **September 28 00:14** — A second database resize and primary switchover resolve the inefficient transaction lookup. * **00:23** — Optional aggregation work is disabled and the remaining customer-facing timeouts end. * **00:26 onward** — Database statistics are refreshed and an optimized composite index is deployed. ## Root Cause The incident resulted from the interaction of four conditions: 1. **Unbounded aggregation:** A synchronous query scanned the full transaction history for given condition. This consumed most database capacity when the high-volume workload began. 2. **Inefficient transaction lookup:** As new records accumulated, database statistics did not refresh quickly enough. The query planner selected an index that scanned a customer’s growing transaction history rather than performing a targeted lookup. 3. **Connection recycling:** Timed-out queries caused database connections to close. Replacement connections repeatedly began with the same inefficient query plan, creating a feedback loop of expensive scans, timeouts, and reconnects. ## Contributing Factors * Our API monitoring excluded the relevant client-timeout responses, and we did not alert on query cancellations or sustained database-connection churn. Database CPU monitor was only configured for non-pagerduty alert * The customer detected the first event before our monitoring did. Delayed engineering escalation extended the response time. * Our first recovery addressed the immediate pressure but did not prevent the workload from triggering a second event when it resumed. ## Resolution and Recovery For the first event, we resized the database and switched to the new primary, then paused the high-volume workload. For the second event, we again resized and switched the primary, then disabled optional aggregation to remove the remaining load. After service recovery, we: * Refreshed database statistics. * Deployed a composite index that gives both new and established connections an efficient transaction-lookup path. * Added database CPU monitors for every production region. * Removed optional, unused aggregation from the `/v1/customers` path * Kept the Australian production database at a higher baseline capacity while we complete the permanent query fixes and capacity review. ## Corrective Actions We are taking the following actions: ### Database and application resilience * Replace the affected transaction lookup with an atomic, consistently indexed operation. * Skip unnecessary historical aggregation and bound any required fallback query. * Evaluate a read pool so issuing-risk reads do not compete with customer-event writes on the primary. * Review steady-state database capacity after the query fixes are complete. ### Monitoring and response * Expand monitoring for client timeouts and database metrics * Improve incident routing so customer reports, support tickets, and on-call escalation converge quickly.

Your product runs on more than Sardine

Add the vendors you depend on and get one message when any of them reports trouble. Free for 3 vendors, no card.

Add your stack →