Slow Failures
An easy SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.
- Domain
- SQL
- Difficulty
- easy
- Seniority
- L3
Problem
Only calls that failed with a client or server error and also ran longer than 200 milliseconds belong in the timeout review. Pull those calls from api_calls, slowest failures first.
SRE is hunting for the endpoints that fail slowly enough to burn timeouts.
Tables
api_calls
Columns: call_id INTEGER, endpoint TEXT, method TEXT, status INTEGER, latency REAL, user_id INTEGER, call_time TEXT, err_msg TEXT
| call_id | endpoint | method | status | latency | user_id | call_time | err_msg |
|---|---|---|---|---|---|---|---|
| 8079 | /api/v1/orders | POST | 200 | 4.2 | 100 | 2026-02-02 01:07:00 | NULL |
| 8158 | /api/v2/products | PUT | 200 | 7.9 | 197 | 2026-03-03 02:14:00 | NULL |
| 8237 | /api/v1/search | DELETE | 201 | 11.6 | 294 | 2026-04-04 03:21:00 | NULL |
| 8316 | /api/v1/auth/login | PATCH | 204 | 15.3 | 391 | 2026-05-05 04:28:00 | NULL |
| 8395 | /api/v1/auth/logout | get | 301 | 19 | NULL | 2026-06-06 05:35:00 | NULL |
| 8474 | /api/v2/analytics | post | 400 | 22.7 | 585 | 2026-07-07 06:42:00 | Not found |
| 8553 | /api/v1/payments | GET | 401 | 26.4 | 682 | 2026-08-08 07:49:00 | Unauthorized |
| 8632 | /api/v1/users/ | POST | 403 | 30.1 | 779 | 2026-09-09 08:56:00 | Rate limit exceeded |
| 8711 | /api/v2/products/ | PUT | 404 | 33.8 | 876 | 2026-01-10 09:03:00 | Internal server error |
| 8790 | /api/v1/users | DELETE | 500 | 37.5 | NULL | 2026-02-11 10:10:00 | Bad gateway |
Expected output
| endpoint | status | latency | err_msg |
|---|---|---|---|
| /api/v1/search | 403 | 1713.7 | NULL |
| /api/v2/products | 401 | 1696.4 | NULL |
| /api/v1/orders | 400 | 1679.1 | NULL |
| /api/v1/users | 503 | 1558 | NULL |
| /api/v1/orders | 503 | 1500 | Service unavailable |
Worked solution and explanation
The column that lies
This is a two-condition filter dressed up as incident triage, and the only real decision is which column gets to define 'failed'. err_msg looks like the honest answer, since a failed call ought to carry a message. In this log it often does not: of the 70 calls that failed and ran past 200 ms, just 24 have a message, and the other 46 carry a 4xx or 5xx status next to a NULL err_msg. Key failure off the message and the review loses two thirds of its incidents, starting with the slowest one, a 403 on '/api/v1/search' at 1713.7 ms.
Getting there
Step 1: Let status define a failure
A client error is the 400s and a server error the 500s, so status >= 400 captures both in one comparison. The log tops out at 503, so there is no upper bound to guard, and a 301 redirect stays out. Narrowing to status >= 500 because 'timeouts are server-side' throws away every slow 401 and 403, and those belong in the result.
Step 2: Require slow AND failed
latency > 200 is the second predicate, joined with AND. Either one alone is wrong in its own direction: status alone pulls in 4xx calls that answered in 30 ms, and latency alone pulls in hundreds of healthy 200s from the busy February traffic. No call sits at exactly 200 ms, but the statement says longer than, so the comparison is strict.
Step 3: Put the slowest at the top
ORDER BY latency DESC hands the reviewer the worst offenders first. A NULL latency never reaches the sort: latency > 200 is unknown for a NULL, so WHERE has already dropped it, and you never have to argue about where NULLs land.
SELECT endpoint, status, latency, err_msg
FROM api_calls
WHERE status >= 400 AND latency > 200
ORDER BY latency DESC- Keyed off the message
WHERE err_msg IS NOT NULL AND latency > 200returns 24 rows. Every failure logged without a message vanishes, including the 1713.7 ms 403 that should top the list.- Keyed off the status
WHERE status >= 400 AND latency > 200returns all 70 failures that crossed the threshold, witherr_msgcarried along as context, NULL where nothing was logged.
Common follow-up questions
- The review now wants only the last seven days. What changes, and why does the query suddenly get cheaper? (Tests whether the candidate connects a `call_time` filter to partition pruning.)
- Two endpoints are stored with stray whitespace, such as '/api/v1/orders '. If the team wants slow-failure counts per endpoint, what do you do first? (Tests normalizing a dirty key with `TRIM` before grouping.)
- How would you return only the single slowest failure per endpoint? (Tests per-group selection with a ranking scoped to each `endpoint`.)