Arketo
All posts

Why is my AI-built app slow? The three patterns behind almost every case

· Arketo team

The app worked fine for weeks. Then real users showed up, and now a page that used to render in four hundred milliseconds takes four seconds, and you're staring at a hosting bill trying to work out what changed.

If that's where you are, some good news: slow AI-built apps are boring. Assistants optimize for "works on the first try," and the shortcuts that make code work on the first try are the same three shortcuts every single time. Figure out which one you've got, and the fix is usually an afternoon.

1. The N+1 query

The assistant writes a loop. Inside the loop, it fetches something from the database. With the 12 rows on your dev machine, nothing happens. With 5,000 rows in production, one page load fires 5,001 queries.

You can spot this one from the outside: pages slow down in proportion to how much data they show. Your dashboard loads fine. Your biggest customer's dashboard times out.

Assistants generate this constantly, and it's honestly not hard to see why. It's the most literal translation of the prompt. "Show each project with its owner's name" becomes "for each project, look up the owner." Correct, readable, quadratically wrong. Point any assistant at the loop and it'll write the join in one go. The hard part was ever noticing the loop.

2. A third-party call sitting on the hot path

Somewhere between the user clicking and the page rendering, your server waits on somebody else's API. Stripe, an email service, an LLM, whatever. The assistant put the call inline because inline made the demo work end to end.

The symptom here is latency with a floor you can't explain. Your own code profiles fast, but the page never comes back in under 800ms, and some days it's mysteriously worse. That floor is someone else's response time, and on their bad days it's your outage. The classic is a checkout that awaits the confirmation email before responding: the email provider hiccups, and suddenly nobody can pay you.

The fix is nearly always the same. Get the call off the hot path. Queue it, background it, fire it after the response, anything. A stranger's slow day shouldn't be your user's problem.

3. The shared resource with a ceiling

This one's sneaky because no line of code is wrong anywhere. The app just gets slow everywhere at once past a certain amount of traffic, and no single endpoint is to blame.

What happened is that something shared hit its limit. Usually it's the database connection pool. The 2026 version: a serverless deployment happily spins up 80 concurrent functions against a Postgres that allows 10 connections. Each function is fast on its own. Collectively, they spend most of their time standing in line.

Watch for slowness that appears at a threshold instead of creeping up gradually. Below some level of traffic everything is fine. Above it, nothing is.

Why you didn't see any of this coming

None of these three live in a file, and that's the real lesson. The N+1 lives between a loop and a schema. The inline email call looks identical to a backgrounded one in a diff. The pool ceiling isn't in your repo at all, it's in a config panel somewhere.

You find them by looking at the shape of the system: what calls what, on which path, leaning on what. That's a diagram question, not a code question, and it's exactly the review vibe coding skips.

It's also what we built Arketo for. Your own assistant draws the architecture it built, and these exact findings get flagged on the diagram, with severity, while the fix is still a one-liner. There's a live demo here. It's cheaper to look now than to let your traffic run the test for you.