Why Is My AI-Built App Slow? A Diagnostic Order
Slow AI-built apps are slow for a short list of predictable reasons, and they appear in a predictable order. Measure first, then work down the list.
Before changing anything, open your browser's developer tools, go to the network tab, and reload the slow page. You are looking for two numbers: how long the slowest single request takes, and how many requests there are. Ninety percent of the time one of those two numbers is obviously wrong, and the answer to why is my AI-built app slow is sitting right there, which is a far better starting point than rewriting code on a hunch.
Measure first, and know what good looks like
A useful target for a page feeling fast is Largest Contentful Paint under 2.5 seconds, measured at the 75th percentile of real loads, which is the threshold web.dev documents for LCP. If your slow page is at four seconds you have a real problem. If it is at 2.8 seconds you have a small one, and it is worth knowing which before you spend a weekend on it.
Do this measurement on a throttled connection as well as your own. AI builders tend to produce apps that feel acceptable on a fast laptop next to the server and unusable on a phone on mobile data, because nothing in the generation process ever tested the second case.
Cause 1: the database is being asked the same question repeatedly
This is the most common cause by a wide margin, and it has a name: the N+1 query problem. Your page fetches a list of twenty orders, then loops over them fetching the customer for each one. That is twenty-one round trips to the database where one or two would do, and each round trip has a fixed cost that has nothing to do with how much data comes back.
It shows up in generated code constantly because writing it that way is the most readable version, and readability is what a model optimises for when nothing tells it otherwise. The symptom is a page that is fine with test data and slow with real data, getting worse in proportion to how much the list contains.
-- one query per order, run inside a loop: N+1
SELECT * FROM orders WHERE user_id = $1;
SELECT * FROM customers WHERE id = $1; -- repeated, once per order
-- one query for everything: the fix
SELECT o.*, c.name, c.email
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.user_id = $1;The fix is usually a join, or the eager-loading mechanism your framework provides. Ask your AI tool directly: find any N+1 query patterns in this file and rewrite them as a single query. It is good at this when pointed at it and will almost never volunteer it unprompted.
Cause 2: no indexes on the columns you filter by
A query filtering on a column without an index makes the database read every row in the table. At a thousand rows nobody notices. At two hundred thousand rows the same query takes seconds, and the change happened gradually enough that no single day felt like a regression.
Every column you filter, sort or join on is an index candidate. Foreign keys especially, because AI builders create the column and the relationship and frequently skip the index, which is invisible until the table grows.
-- find slow queries first, then index what they filter on
CREATE INDEX idx_orders_user_id ON orders (user_id);
CREATE INDEX idx_orders_created_at ON orders (created_at DESC);Do not index everything. Each index makes writes slower and takes space. Index what your slow queries actually filter on, which you know from measuring rather than from guessing.
Cause 3: images shipped at their original size
A hero image straight from a camera is several megabytes and gets displayed at 800 pixels wide. The browser downloads the whole thing and throws most of it away. This single issue accounts for a large share of poor LCP scores on content-heavy pages, and it is the cheapest thing on this list to fix.
Resize to the largest size actually displayed, then serve smaller versions for smaller screens.
Use a modern format. WebP is broadly supported and typically 25 to 35 percent smaller than an equivalent JPEG.
Set width and height attributes so the browser reserves space and the page stops jumping while it loads.
Lazy-load anything below the fold, and never lazy-load the main image at the top, which is a common and self-defeating mistake.
The web.dev guide to optimising LCP goes deeper on the loading sequence if the largest element on your page is an image, which it usually is.
Cause 4: the AI calls themselves are the slow part
If your app calls a language model during a page load, that call is almost certainly the slowest thing happening, and no amount of database tuning will hide a three-second model response behind a two-hundred-millisecond query.
Move the call out of the request path. Trigger it in the background and show the result when it arrives rather than making the user wait for it.
Stream the response if the user is reading it. Text appearing after 400ms feels dramatically faster than the same text appearing complete after three seconds.
Cache aggressively. The same prompt with the same input produces an answer you already have, and a surprising share of production traffic is repeats.
Use a smaller model for the parts that do not need the big one. Classification and extraction rarely need your most capable model.
The last point cuts your bill at the same time it cuts your latency, which is unusual and worth exploiting. The options are laid out in how to reduce AI API costs.
Cause 5: everything is being loaded before anything is shown
Generated frontends commonly fetch all the data a page could need, wait for all of it, and then render. One slow request holds the entire page hostage while the other nine finished in fifty milliseconds.
Render what you have as it arrives. Show the list first and fill in the counts when they load. Users perceive a page that appears progressively as much faster than one that appears complete a second later, even when the total time is identical, because the first one gives them something to read immediately.
The order to work in
Step | What you check | Typical time to fix |
|---|---|---|
1 | Network tab: slowest request, and number of requests | 5 minutes to measure |
2 | Many small identical requests: N+1 queries | An hour |
3 | One slow query: missing index | 10 minutes |
4 | One huge asset: unoptimised image | 20 minutes |
5 | One slow call: a model in the request path | Half a day, because it changes the interaction |
6 | Everything waiting on one thing: serial loading | Half a day |
Work top to bottom and stop when the page is fast enough. Performance work has sharply diminishing returns, and the difference between four seconds and two is worth far more than the difference between two seconds and 1.8.
Two related problems worth separating out: if the app is slow only under real usage rather than in testing, the shape of the problem is different, and what it costs to run an AI-built app covers where hosting choices become the constraint. If the code is doing something you did not expect at all, start with debugging AI-generated code instead, because you have a correctness problem wearing a performance problem's clothes.
Keeping performance from decaying again is a maintenance question rather than a fix, and the checks that catch it early are in AI app maintenance.
FAQ
Why is my app fast locally and slow in production?
Usually distance and data volume. Locally the database is on the same machine and holds test data. In production there is a network hop between app and database, and the tables are large enough for missing indexes to matter.
Should I upgrade my hosting plan to fix slowness?
Rarely, and not first. More CPU does not fix an N+1 query or a four-megabyte image; it makes the same inefficiency slightly less painful at a higher monthly cost. Measure before you upgrade.
How do I find slow database queries?
Most managed databases have a slow query log or a performance panel showing the queries taking longest and running most often. Start there rather than reading code, because the offender is frequently a query you did not know your framework was issuing.
Can I just ask the AI to make my app faster?
Only with a specific target. Make this app faster produces scattered changes. Paste the slow query with its execution plan, or name the file and the symptom, and the same tool becomes reliable because the problem is now well defined.
How did this land?
About the author

Developer Advocate
Steve builds something with Swarmz every week and writes up what worked, what broke, and what he'd do differently. Tutorials and hands-on guides are his lane.


