Skip to content
spot_the_ai_bug

Performance traps: interview questions

A performance trap is correct code with the wrong complexity: quadratic loops, serialized I/O, or queries the database can't use an index for.

How to spot it in code review

  • Ask how the code behaves at 100x the test input.
  • Look for lookups or copies inside loops.
  • Look for independent awaits that run one after another.
  • Check that WHERE clauses can use an index on the raw column.

Why AI-generated code gets this wrong

The most direct translation of a requirement is usually the slow one, and small examples hide the cost.

Performance traps: 3 practice questions

Q1TypeScriptmedium

Awaiting requests one by one

loadAvatars() fetches 50 independent user profiles for a team page. It takes ~10 seconds. Why?

export async function loadAvatars(userIds: string[]): Promise<string[]> {  const avatars: string[] = [];  for (const id of userIds) {    const res = await fetch(`/api/users/${id}`);    const user: { avatarUrl: string } = await res.json();    avatars.push(user.avatarUrl);  }  return avatars;}
Show answer

line 4 · Performance trap

Each request waits for the previous one to finish, so total time is the sum of all latencies (50 × ~200ms). The requests are independent and can run concurrently.

Fix
export async function loadAvatars(userIds: string[]): Promise<string[]> {  return Promise.all(    userIds.map(async (id) => {      const res = await fetch(`/api/users/${id}`);      const user: { avatarUrl: string } = await res.json();      return user.avatarUrl;    }),  );}

Interview follow-up: Strong candidates add that very large lists need a concurrency limit, or a batch endpoint.

Q2Javamedium

Building a CSV with +=

toCsv() exports 200k rows. It takes minutes and churns the garbage collector. Why?

public static String toCsv(List<String[]> rows) {    String csv = "";    for (String[] row : rows) {        csv += String.join(",", row) + "\n";    }    return csv;}
Show answer

line 4 · Performance trap

Strings are immutable, so each += copies everything built so far into a new string. Over n rows that is O(n²) copying and a huge amount of garbage.

Fix
    StringBuilder csv = new StringBuilder();    for (String[] row : rows) {        csv.append(String.join(",", row)).append('\n');    }    return csv.toString();

Interview follow-up: Mention that the compiler's StringBuilder optimization applies within a single expression, not across loop iterations.

Q3SQLhard

Leading-wildcard LIKE

users has 30M rows and a B-tree index on email. This query takes 20 seconds. Why?

SELECT COUNT(*)FROM usersWHERE email LIKE '%@gmail.com';
Show answer

line 3 · Performance trap

A B-tree index is ordered by the start of the value, so a pattern that starts with % can't use it. The database scans all 30M rows.

Fix
-- Store the domain separately (or use a generated column) and index it:ALTER TABLE users ADD COLUMN email_domain TEXT    GENERATED ALWAYS AS (split_part(email, '@', 2)) STORED;CREATE INDEX ON users (email_domain); SELECT COUNT(*) FROM users WHERE email_domain = 'gmail.com';

Interview follow-up: Alternatives worth naming: an index on reverse(email), or a trigram (pg_trgm) index for general substring search.

Every day, everyone gets the same pull request written by AI. It looks clean. It has comments. It has exactly one real bug.

  1. 1

    Find the line

    Tap the buggy line, then hit Submit. You get 3 attempts.

  2. 2

    Read the hints

    A miss within 2 lines is 🔥 Warm. Anything further is ❄️ Cold.

  3. 3

    Name the bug

    Found it? Bonus round: pick the bug type from 4 options. It doesn't affect your win, just your bragging rights.

// your share card

found in 3/3

🟥 cold miss · 🟨 warm miss · 🟩 found · ⬛ unused

Keyboard: ↑ ↓ to move between lines, Enter to submit. A new bug drops every day at midnight IST.

0
Played
0
Win %
0
Streak
0
Max

Attempts distribution