Launch offer: the first 1,000 users get Settl free for a year*Claim your spot
settlbuilding in public

Replace the Loop That Explodes With Real Data

Ten rows can hide almost any performance mistake. Ten thousand cannot. The classic version is a loop that scans another list for every item. At 10 by 10, that is 100 comparisons. At 10,000 by 10,000, it is 100 million.

Big O is a way to describe how work grows as input grows. You do not need the notation to find the bug. Count the repeated work.

Find the hidden multiplication

Look for code shaped like this:

const enriched = orders.map((order) => ({
  ...order,
  customer: customers.find((customer) => customer.id === order.customerId),
}));

find starts at the beginning of customers for every order. Build an index once instead:

const customersById = new Map(customers.map((customer) => [customer.id, customer]));
const enriched = orders.map((order) => ({
  ...order,
  customer: customersById.get(order.customerId),
}));

The first version repeatedly scans. The second pays once to build the map, then performs direct lookups.

Keep semantics before speed

A Map changes behaviour if duplicate keys exist. A Set removes duplicates. Sorting can change display order. Before replacing a data structure, write down:

The faster answer is wrong if it silently chooses a different duplicate or stale value.

Benchmark the curve

Use the same deterministic fixtures at 10, 100, 1,000, and 10,000 records. Warm up the runtime, run each case several times, and record median plus a slow percentile. Do not compare two versions on different data.

The useful signal is not one timing. It is the shape. If doubling input makes runtime roughly four times worse, you likely have quadratic work somewhere in the measured path.

Also measure memory. The Map version stores an extra index, which is often the right trade, but it is not free.

What Claude can help with

Claude can inventory nested loops, repeated scans, repeated parsing, and array methods inside hot paths. Ask it to explain what n represents and which behaviour must stay identical. Then make it write correctness tests before the replacement.

Do not accept "this is O(n)" as evidence. The benchmark and call count are the evidence.

Run the starter locally

npm test
npm run validate
npm run sample

Dry-run validates the operation, data sizes, timings, and correctness-test inputs. Docker Compose runs the Node service and n8n without modifying your codebase.

Download the runnable pack

Get the next one in your inbox