Rush Hour API Latency

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
Asked in
Lyft

Problem

Across every day in api_calls, what is the average latency in each hour from 15:00 through 17:59, earliest hour first? That table logs only the us-east traffic an on-call engineer is sizing afternoon capacity for.

Rush hour hits the API differently.

Tables

api_calls

Columns: call_id INTEGER, endpoint TEXT, method TEXT, status INTEGER, latency REAL, user_id INTEGER, call_time TEXT, err_msg TEXT

api_calls: 10 of 670 rows
call_idendpointmethodstatuslatencyuser_idcall_timeerr_msg
8079/api/v1/ordersPOST2004.21002026-02-02 01:07:00NULL
8158/api/v2/productsPUT2007.91972026-03-03 02:14:00NULL
8237/api/v1/searchDELETE20111.62942026-04-04 03:21:00NULL
8316/api/v1/auth/loginPATCH20415.33912026-05-05 04:28:00NULL
8395/api/v1/auth/logoutget30119NULL2026-06-06 05:35:00NULL
8474/api/v2/analyticspost40022.75852026-07-07 06:42:00Not found
8553/api/v1/paymentsGET40126.46822026-08-08 07:49:00Unauthorized
8632/api/v1/users/POST40330.17792026-09-09 08:56:00Rate limit exceeded
8711/api/v2/products/PUT40433.88762026-01-10 09:03:00Internal server error
8790/api/v1/usersDELETE50037.5NULL2026-02-11 10:10:00Bad gateway

Expected output

First 3 of 3 rows
houravg_latency
15326.008
16348.5103448275862
17339.4916666666667

Worked solution and explanation

What this really is

This is time-of-day bucketing dressed up as capacity planning. call_time is a full timestamp spread over years of traffic, and the question wants three buckets that recur every single day: the 15, 16 and 17 o'clock hours. No contiguous stretch of timestamps is 'the afternoon peak', so any range filter on call_time catches one afternoon or one arbitrary span. The skill is pulling the hour out of each row and letting that one derived value do double duty, as the filter and as the bucket. Get it wrong and capacity gets sized off a single afternoon, or off one blended number that hides how latency climbs through the peak.

Building it

Step 1: Derive the hour from call_time

call_time is stored as text like '2026-06-15 16:01:00'. strftime('%H', call_time) pulls out '16', but as a string. CAST(... AS INTEGER) turns it into a number you can compare against 15 and 17 and that sorts numerically.

Step 2: Filter on the hour, not the timestamp

BETWEEN 15 AND 17 is inclusive on both ends, and because you compare whole hours, 17 already covers 17:00 through 17:59. < 18 says the same thing; <= 18 quietly drags in the 18 o'clock rush.

Step 3: Bucket by that same hour and average

Group on the alias hour and take AVG(latency). Two calls inside the window never recorded a latency; AVG skips those NULLs, which is right, since a missing measurement is not a zero-millisecond call.

Step 4: Read the peak in order

ORDER BY hour lays the three buckets out from 15 to 17, so the climb across the afternoon reads top to bottom.

Average latency per peak hour
SELECT
    CAST(strftime('%H', call_time) AS INTEGER) AS hour,
    AVG(latency) AS avg_latency
FROM api_calls
WHERE CAST(strftime('%H', call_time) AS INTEGER) BETWEEN 15 AND 17
GROUP BY hour
ORDER BY hour
Timestamp range
WHERE call_time BETWEEN '... 15:00:00' AND '... 17:59:59' keeps one contiguous slice of time. On a log spanning years it catches one afternoon and, without a bucket, returns one number.
Hour of day
WHERE CAST(strftime('%H', call_time) AS INTEGER) BETWEEN 15 AND 17 keeps the peak hours of every day, and grouping on that hour returns the three rows the planning question needs.
The version that sizes capacity off one afternoon
SELECT AVG(latency) AS avg_latency
FROM api_calls
WHERE call_time BETWEEN '2026-06-15 15:00:00' AND '2026-06-15 17:59:59'

One day, one blended figure: the shape candidates write when they read the window as a timestamp interval.

Common follow-up questions