DEV Community

Cover image for Back to Code | Ep 04: Forgetting the Machine — Big O and the Performance Tax
Mehmet TURAÇ
Mehmet TURAÇ

Posted on

Back to Code | Ep 04: Forgetting the Machine — Big O and the Performance Tax

The 15-week technical battle of LogiFlow — a company waking up from the illusion created by artificial intelligence and returning to real engineering.

The Story

Architecture was fixed. Tests now measured real intent. The system was logically flawless. But then a P0 complaint came from a customer: "The Monthly Logistics Report screen takes 18 seconds to load!"

Emre said he trusted the code AI wrote. It was readable, full of map and filter.

Defne ran EXPLAIN ANALYZE on the database and saw the truth.

Technical Autopsy: The N+1 Query Inferno

// AI: O(N²) and N+1 Hell
const trucks = await prisma.truck.findMany();

const reports = await Promise.all(
  trucks.map(async (t) => {
    // 1000 trucks = 1000 separate queries fired!
    const deliveries = await prisma.delivery.findMany({
      where: { truckId: t.id }
    });
    return { truck: t, total: deliveries.length };
  })
);
Enter fullscreen mode Exit fullscreen mode

The code looked elegant. Readable. Clean. But under the hood, for every truck in the database, it fired a separate SELECT query for deliveries. With 1,000 trucks, that meant 1,001 database queries instead of 1.

Defne pulled up the EXPLAIN ANALYZE output:

"Look at this. 1,000 sequential queries, each doing a full table scan on the deliveries table. The database is literally choking."

The Human Fix: Thinking at the Database Level

// Single JOIN/Count query
const reports = await prisma.truck.findMany({
  include: {
    _count: { select: { deliveries: true } }
  }
});
// 18 seconds → 120 milliseconds
Enter fullscreen mode Exit fullscreen mode

One query. One round trip. The database does what it does best — joining and counting in a single pass.

Back to the Metal

AI doesn't feel the physical limits of RAM and CPU Cache. Thinking at the machine level — Back to the Metal — is the human's job.

  • EXPLAIN ANALYZE results
  • pprof, JProfiler, async-profiler
  • Flame graphs
  • Cache hit ratios

These aren't optional nice-to-haves. They're the instruments a surgeon reads during an operation. AI writes code that compiles. Humans write code that performs.

"AI generates O(N²) algorithms hidden behind beautiful functional syntax. It takes a human to see the invisible cost."

Big O Didn't Retire

Modern frameworks and ORMs can hide quadratic complexity behind elegant APIs. But Big O notation didn't retire just because we stopped writing C.

What AI Writes What Actually Happens
trucks.map(t => getDeliveries(t)) N+1 queries, O(N²) I/O
array.filter().map().reduce() 3 full passes over the array
Nested Promise.all Exponential connection pressure

The abstractions are beautiful. The performance cost is real.

Lessons from Episode 4

1. N+1 Problem: AI tends to write loops that fire separate queries for each entity. Always check your ORM's generated SQL.

2. Big O Isn't Forgotten: Modern frameworks and ORMs can hide O(N²) algorithms behind clean syntax. Profile before you trust.

3. CPU Cache and Memory: AI doesn't account for cache locality, false sharing, or garbage collection pressure. When milliseconds matter, a human must reach for the profiler.

4. EXPLAIN ANALYZE Is Your X-Ray: Never trust query performance without checking the execution plan. The database tells you the truth — if you ask.


This is Episode 4 of the "Back to Code" series. Next up: Episode 5 — The Revenge of Context: DDD and the "Context" AI Cannot Grasp.

Series: back.to.code · 2026

Top comments (0)