Top 5 Slowest DNS Lookups
A medium SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.
- Domain
- SQL
- Difficulty
- medium
- Seniority
- L3
Problem
List the domain and record type pairs with the five longest worst-case lookups in dns_lookups, slowest first, for the network team's latency review. If pairs tie for fifth, keep every one of them.
Five DNS lookups that took too long.
Tables
dns_lookups
Columns: lookup_id INTEGER, domain TEXT, rec_type TEXT, ttl_secs INTEGER, status TEXT, latency REAL, looked_at TEXT
| lookup_id | domain | rec_type | ttl_secs | status | latency | looked_at |
|---|---|---|---|---|---|---|
| 129 | cdn.example.com | AAAA | 47 | NXDOMAIN | 0.47 | 2026-02-02 01:03:00 |
| 158 | auth.example.com | CNAME | 64 | SERVFAIL | 0.84 | 2026-03-03 02:06:00 |
| 187 | search.example.com | MX | 81 | TIMEOUT | 1.21 | 2026-04-04 03:09:00 |
| 216 | db.internal.net | TXT | 98 | REFUSED | 1.58 | 2026-05-05 04:12:00 |
| 245 | cache.internal.net | NS | 115 | NOERROR | 1.95 | 2026-06-06 05:15:00 |
| 274 | example.com | A | 132 | NXDOMAIN | 2.32 | 2026-07-07 06:18:00 |
| 303 | www.example.com | AAAA | 149 | SERVFAIL | 2.69 | 2026-08-08 07:21:00 |
| 332 | API.example.com | CNAME | NULL | TIMEOUT | 3.06 | 2026-09-09 08:24:00 |
| 361 | Cdn.Example.Com | MX | 183 | REFUSED | 3.43 | 2026-01-10 09:27:00 |
| 390 | api.example.com | TXT | 200 | NOERROR | NULL | 2026-02-11 10:30:00 |
Expected output
| domain | rec_type | max_latency |
|---|---|---|
| Cdn.Example.Com | MX | 36.73 |
| API.example.com | CNAME | 36.36 |
| www.example.com | AAAA | 35.99 |
| example.com | A | 35.62 |
| cache.internal.net | NS | 35.25 |
Worked solution and explanation
This is a top five of groups dressed up as a top five of lookups. Anyone can sort by latency. The skill being probed is whether you collapse each domain and rec_type pair to its single worst lookup before you cut the list. Skip that and dns_lookups hands you the same pair twice. Every lookup in this log is recorded twice at the same latency, so the raw top five covers three pairs, and two of the real offenders never make the report.
What the raw top five returns
SELECT domain, rec_type, latency
FROM dns_lookups
ORDER BY latency DESC
LIMIT 5;Returns Cdn.Example.Com MX twice, API.example.com CNAME twice and www.example.com AAAA once: three pairs in five rows.
Building the answer
Step 1: Collapse each pair to its worst lookup
Group dns_lookups by domain and rec_type and take MAX(latency) as max_latency. The question is about a pair's worst case, so one row per pair is the grain everything after this works on. MAX skips NULLs, so a pair keeps its slowest timed lookup even when some of its lookups never recorded one.
Step 2: Number the pairs by worst case, ties sharing a place
DENSE_RANK() OVER (ORDER BY MAX(latency) DESC) runs after the grouping, so it sees thirty pairs, not two hundred lookups. Pairs with the same maximum get the same number, and the next value takes the next number. That is exactly what keeping every pair tied for fifth asks for.
Step 3: Cut at five, then sort slowest first
A window result cannot be filtered in the WHERE of the query that computes it, so the pair_worst CTE holds the numbered pairs and the outer query keeps latency_rank <= 5. Then ORDER BY max_latency DESC delivers slowest first. That is the only order promised, so no tiebreaker is owed.
WITH pair_worst AS (
SELECT domain,
rec_type,
MAX(latency) AS max_latency,
DENSE_RANK() OVER (ORDER BY MAX(latency) DESC) AS latency_rank
FROM dns_lookups
GROUP BY domain, rec_type
)
SELECT domain, rec_type, max_latency
FROM pair_worst
WHERE latency_rank <= 5
ORDER BY max_latency DESC;- A fixed five rows
ORDER BY max_latency DESC LIMIT 5after the grouping returns exactly five rows. It matches today only because no two pairs share a maximum. The day two pairs tie for fifth, one is dropped, and the engine decides which.- Five worst-case values
DENSE_RANK()withlatency_rank <= 5keeps every pair holding one of the five longest worst cases. A tie for fifth lengthens the list instead of silently truncating it.
Common follow-up questions
- How would you return the five slowest record types for each domain instead? (Moves the cut inside each `domain` with `PARTITION BY domain`.)
- What changes if the team wants the 95th percentile latency per pair instead of the worst lookup? (Swaps `MAX` for a percentile aggregate and asks how ties behave on a smoother metric.)
- How would you show whether a pair's worst case is getting worse month over month? (Adds a month bucket from `looked_at` and compares each month with the one before.)