Why Your AI-Built App Is Slow (And How to Fix It)
AI tools ship fast but create slow apps. Duplicate requests, blocking loading states, missing code splitting, and heavy bundles - here's how to find and fix every speed bottleneck.
By Daniel A · Kraftwire Software
· 10 min readThe Cost of Slow
Before we dive into the technical fixes, let's talk about what slow actually costs you:
**7% conversion loss** for every 1-second delay in load time
**53% of mobile users** abandon pages that take over 3 seconds to load
**11% fewer page views** per second of delay
**16% drop in customer satisfaction** per second of delay
Sites loading in **1 second convert 2.5x more** than sites loading in 5 seconds
The Economic Times improved their Core Web Vitals and saw a **43% reduction in bounce rates**
These aren't theoretical numbers. They come from Google's Core Web Vitals research, Deloitte's milliseconds study, and real-world case studies from companies that measured the business impact of speed improvements.
**Speed is not a technical detail. It's a revenue lever.**
AI Writes Fast Code That Runs Slowly
AI coding tools like Lovable, Cursor, Bolt.new, and Replit can build a full-stack app in minutes. But there's a pattern we see in almost every AI-generated codebase: **the app works, but it's slow.**
Not "a few milliseconds slow." We're talking 500ms–2000ms of unnecessary loading time, 30-40% larger JavaScript bundles than needed, and 2-4 redundant network requests on every page load.
These aren't bugs. The app functions correctly. But users feel the sluggishness, and it costs you conversions, engagement, and trust.
SimplyScan now includes **Speed Optimization** as a dedicated scan category - the 14th category in our scanner. Here are the 10 most common speed issues we find.
1. Duplicate Network Requests on Load
**The problem:** AI-generated auth providers commonly call both `onAuthStateChange` and `getSession()` on mount. The `onAuthStateChange` listener fires with `INITIAL_SESSION` synchronously, so the manual `getSession()` call is redundant. This doubles your auth-related requests.
// ❌ AI-generated pattern - 2x redundant requests
useEffect(() => {
supabase.auth.onAuthStateChange((event, session) => {
checkAdmin(session); // fires on INITIAL_SESSION
checkProStatus(session);
});
// This duplicates the above:
supabase.auth.getSession().then(({ data }) => {
checkAdmin(data.session);
checkProStatus(data.session);
});
}, []);
**The fix:** Remove the manual `getSession()` call. Let `onAuthStateChange` handle everything.
// ✅ Fixed - single source of truth
useEffect(() => {
const { data: { subscription } } = supabase.auth.onAuthStateChange(
(event, session) => {
checkAdmin(session);
}
);
return () => subscription.unsubscribe();
}, []);
**Impact:** -2 to -4 network requests per page load.
2. Blocking Loading States (Full-Page Spinners)
**The problem:** AI tools love wrapping entire pages in loading gates. A CMS provider fetches content from the database, and every page - including Login, Signup, Terms, Privacy - shows a blank screen until the database responds.
// ❌ Every page waits for CMS data
if (loading) return <div className="min-h-screen" />;
**The fix:** Use React Query with `staleTime: Infinity` and render immediately with hardcoded defaults. Swap in CMS data seamlessly when it arrives.
**Impact:** ~500ms faster First Contentful Paint.
3. Missing Code Splitting
**The problem:** All page components are eagerly imported in the router. A visitor hitting the homepage downloads JavaScript for Dashboard, ScanResults, AdminPanel, BlogPost, and every other page.
// ❌ Everything in one bundle
import Dashboard from "./pages/Dashboard";
import AdminPanel from "./pages/AdminPanel";
import BlogPost from "./pages/BlogPost";
**The fix:** Use `React.lazy` for all routes except the landing page.
// ✅ Code-split routes
const Dashboard = lazy(() => import("./pages/Dashboard"));
const AdminPanel = lazy(() => import("./pages/AdminPanel"));
const BlogPost = lazy(() => import("./pages/BlogPost"));
**Impact:** 30-40% smaller initial JavaScript bundle.
4. Heavy Bundle Dependencies
**The problem:** AI tools import full libraries for simple tasks. The most common offender is `framer-motion` (~45KB gzipped) imported in 10+ components just for simple fade-in-on-scroll animations that CSS can handle natively.
// ❌ 45KB library for a simple fade
import { motion } from "framer-motion";
<motion.div whileInView={{ opacity: 1 }}>Hello</motion.div>
**The fix:** Replace with CSS animations for simple effects. Keep framer-motion only for complex animations (stacking cards, stagger sequences).
/* ✅ Zero-cost CSS alternative */
.animate-fade-in-up {
animation: fadeInUp 0.5s ease-out forwards;
}
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
**Impact:** ~45KB less JavaScript to parse and execute.
5. Missing Query Cache Optimization
**The problem:** React Query defaults to `staleTime: 0`, meaning data re-fetches on every component mount and navigation. Blog posts that change once a week re-fetch every time you click "Back."
// ❌ Re-fetches on every mount
const { data } = useQuery({ queryKey: ["posts"], queryFn: fetchPosts });
**The fix:** Add appropriate `staleTime` for content that doesn't change frequently.
// ✅ Cache for 5 minutes
const { data } = useQuery({
queryKey: ["posts"],
queryFn: fetchPosts,
staleTime: 5 * 60 * 1000,
});
**Impact:** Eliminates unnecessary re-fetches, faster navigation.
6. Theme Flash on Load
**The problem:** The theme (dark/light) is determined in React after hydration. On hard refresh, there's a brief flash of the wrong theme - white background flashing before dark mode kicks in, or vice versa.
**The fix:** Add a synchronous script in `index.html` (before React loads) that reads `localStorage.theme` and sets `class="dark"` on `<html>` immediately.
<script>
var t = localStorage.getItem('theme');
if (t === 'dark' || (!t && matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
}
</script>
**Impact:** Zero theme flash - correct theme from the first frame.
7. Missing Image Preloading
**The problem:** Hero images are the largest element above the fold (LCP - Largest Contentful Paint). But AI-generated code imports them as ES6 modules or uses lazy loading on above-the-fold images.
**The fix:** Add `<link rel="preload" as="image">` for the first hero image in `index.html`, and use `fetchPriority="high"` on the hero `<img>` element.
**Impact:** ~200ms faster LCP.
8. Unnecessary Data Fetching
**The problem:** A blog post page fetches ALL blog posts just to show 3 "related articles" at the bottom. That's 50+ posts loaded when only 3 are needed.
**The fix:** Create a lightweight query that fetches only 3 recent posts, or defer the fetch until the user scrolls to the related section.
**Impact:** Less data transferred, faster page render.
9. Third-Party Scripts Loading Eagerly
**The problem:** Analytics SDKs, feedback widgets, and chat widgets load on every page, even if they're only used in specific contexts.
// ❌ Feedback SDK loads for every visitor
import { FeedbackFish } from "@feedback-fish/react";
**The fix:** Lazy-load non-critical third-party components.
// ✅ Only loads when Footer is visible
const FeedbackButton = lazy(() => import("./FeedbackButton"));
**Impact:** Smaller initial bundle, faster interactive time.
10. Render-Blocking CSS and Fonts
**The problem:** Google Fonts loaded synchronously block rendering until the stylesheet is downloaded and parsed.
**The fix:** Use `rel="preload"` with `onload` swap pattern, or use `font-display: swap` to show fallback fonts immediately.
<link rel="preload" as="style"
href="https://fonts.googleapis.com/css2?family=Inter&display=swap"
onload="this.onload=null;this.rel='stylesheet'" />
**Impact:** Faster First Contentful Paint, no render blocking.
The Compound Effect
Each individual optimization saves 100-500ms. But they compound:
| Optimization | Estimated Impact |
|---|---|
| Fix duplicate auth requests | -2 to -4 requests |
| Remove loading gates | ~500ms faster FCP |
| Code splitting | ~30-40% smaller JS |
| Remove heavy dependencies | ~45KB less parsed |
| Add query caching | Fewer re-fetches |
| Theme pre-hydration | No flash |
| Preload hero image | ~200ms faster LCP |
**Total: 500-1500ms faster perceived load, 30-40% smaller bundle.**
What Your Users Actually Experience
Speed isn't just a metric - it's a feeling. Here's what changes when you fix these issues:
**Before optimization:**
Users see a blank screen or spinner for 2-3 seconds
Every page navigation triggers a full re-fetch, causing flicker
The page "jumps" as fonts and images load late
Interactions feel sluggish - clicks take 200-500ms to respond
Users leave before they ever see your product
**After optimization:**
Content appears in under 1 second - instant, snappy, professional
Navigation feels like a native app - no spinners, no flicker
No layout shift - the page loads exactly as designed
Interactions respond immediately - the app feels alive
Users stay longer, convert more, and trust your product
This is the difference between an app that works and an app that wins. Your users can't see your code, but they feel every millisecond of delay. A fast app builds trust. A slow app erodes it.
*Sources: Google CrUX 2025, Reboot Online, Deloitte "Milliseconds Make Millions" study, Blogging Wizard, The Economic Times Core Web Vitals case study.*
SimplyScan Now Scans for Speed
Speed Optimization is the 14th category in SimplyScan's scanner. The free scan identifies all speed issues in your app and gives you 1 full fix recommendation. Upgrade to Pro for the complete optimization audit with code examples and AI fix prompts for every issue found.
Run a free scan now - it takes 30 seconds and covers 4 categories including speed. Or go Pro for all 14 categories and 51+ checks.
Related Reading
[Speed = Revenue: What the Data Says](/blog/speed-equals-revenue-case-studies) - real case studies proving faster apps convert more
[Why Cursor, Lovable, and Bolt Don't Optimize Speed](/blog/speed-optimization-vs-ai-tools) - the gap between development speed and runtime speed
[Performance as a Security Risk](/blog/performance-security-guide) - how slow code creates denial-of-service vulnerabilities
[Free vs Pro Scan: What's the Difference?](/blog/free-vs-pro-scan-comparison) - speed optimization is included in SimplyScan's 14th scan category