NotVibesCoded logo

Your vibe-coded site is slow. Here's the 20-fix checklist.

AI-built sites ship fast and load slow. Twenty fixes, grouped by where the slowness lives: frontend, network, backend, and the process that keeps it fast.

Published 4 min read

AI coding tools are incredible at shipping features and terrible at shipping fast features. The generated code works — it just loads 4MB of JavaScript, fetches images at full resolution, and queries the database like it's 2009.

If your vibe-coded site feels sluggish, work through this list in order. Each fix is small; together they're the difference between a 12-second load and a 1-second one.

Frontend: what the browser downloads and renders

1. Compress all images. The single biggest win on most sites. Convert to WebP or AVIF, strip metadata, and size images to their display dimensions — not the 4000px original your phone captured. A 2MB hero image becomes 150KB with zero visible difference.

2. Lazy-load below-the-fold images. If it isn't visible on first paint, it shouldn't block first paint. Native loading="lazy" is one attribute and works everywhere modern.

3. Split your code into chunks. AI tools love single giant bundles. Route-based code splitting means the homepage doesn't download the admin dashboard's JavaScript. Most frameworks do this automatically once you stop fighting the defaults.

4. Minify JS and CSS. Your build tool probably does this in production already — verify it. Unminified output from an agent's dev-mode setup can double your payload.

5. Defer non-critical scripts. Analytics, chat widgets, and embeds don't need to block rendering. defer or async them, or load on interaction. If the page works without it for the first 3 seconds, it can wait.

6. Reduce unnecessary re-renders. AI-generated React components re-render on every keystroke because nothing is memoized and state lives too high. Profile first, then memoize the hot paths and colocate state. Don't memoize everything — that's its own performance problem.

7. Debounce input handlers. Search-as-you-type firing an API call per keystroke is how you DDoS yourself. Debounce at 200–300ms: wait for the user to pause, then fire once.

8. Paginate large lists. Rendering 5,000 rows because "the data was there" is a classic agent move. Paginate, virtualize, or infinite-scroll — never dump the whole dataset into the DOM.

9. Add loading skeletons. Not strictly speed, but perceived speed. A shimmer placeholder beats a blank page or a spinner — users tolerate waiting when they can see structure forming.

10. Remove unused dependencies. Agents install packages enthusiastically. Audit your bundle: that date library imported for one format call, the lodash you use twice. Fewer dependencies, smaller bundle, fewer supply-chain surprises.

Network: how bits travel

11. Put a CDN in front. Static assets served from one region are slow everywhere else. A CDN (Cloudflare's free tier counts) caches at the edge and typically cuts asset load times by half or more worldwide.

12. Compress API payloads. Enable Brotli or gzip on your server. JSON compresses beautifully — a 500KB response becomes 60KB. This is usually one config line and agents never add it.

13. Cache API responses. Not every request needs fresh data. Cache GET responses with sensible TTLs — at the CDN edge, in a reverse proxy, or in the client. Dashboards showing "data from 5 minutes ago" are fine for 95% of use cases.

Backend: where the real slowness hides

14. Index your database. The agent created the tables; it didn't create the indexes. Find your slow queries (every database has a slow-query log), add indexes on the filtered and joined columns, and watch response times drop 10–100x.

15. Fix N+1 queries. The signature AI-generated backend bug: fetch 100 items, then 100 separate queries for each item's author. One hundred and one queries where one join would do. Use eager loading / select_related / prefetch_related — whatever your ORM calls it.

16. Add connection pooling. Opening a fresh database connection per request wastes 50–200ms each time. A pooler (PgBouncer for Postgres, or your framework's built-in pool) reuses connections. Essential the moment you have real traffic.

17. Cache expensive computed results. If you're recomputing the same dashboard aggregation on every page load, stop. Cache it in Redis or even in-process memory with a TTL. Compute once, serve many.

18. Enable server-side caching. Full-page or fragment caching for content that doesn't change per user: marketing pages, docs, public listings. A cached page serves in single-digit milliseconds.

19. Add a load balancer — when you need one. This is the only item on the list that's premature for most sites. One well-tuned server handles shocking amounts of traffic. Add the load balancer when monitoring says you're saturating, not before.

Process: staying fast

20. Run a Lighthouse audit. Do this first and last. First, to know your baseline and find the biggest offender (it's usually images). Last, to verify the fixes worked. Then put it in CI so the next AI-generated PR can't quietly regress everything you just fixed.


The pattern behind all twenty: AI tools optimize for working, not for fast. That's fine — speed was never the demo. But production has users, and users leave slow sites. Run the audit, fix the big rocks first (images, N+1s, missing indexes), and make performance a gate, not an afterthought.

Related articles