Table of Contents
Replit Agent 4 vs Bolt.new vs Lovable.dev: Which AI App Builder Actually Ships a Production CRUD App in 30 Minutes
Pick Bolt.new. On the same production CRUD spec it hit a running preview at 6:11 and a live Vercel URL at 17:58, fastest start of the three, with one cheap, one-prompt failure to fix. The call flips in exactly two cases: you need a Git-auditable history from the first generation (Lovable.dev), or you need an IDE with checkpoint rollback because your build will break and you want to recover instead of re-prompt (Replit Agent 4). It does not flip on "production-readiness," because none of the three solves the one genuinely hard part of this spec.
That hard part is multi-tenant subdomain routing, and the reason all three stub it is structural, not a maturity gap. Subdomain-to-tenant mapping needs a wildcard DNS record and a reverse proxy or edge middleware that reads the Host header before the app boots. None of that lives inside the builder's generated codebase. It lives in your DNS zone and your hosting platform's routing layer, which the agent cannot see or provision. Every one of them gives you tenant data isolation (schema prefix or tenant ID) and then hands you the routing. Budget a fixed 10-15 minutes for it regardless of which tool you pick.
So the real question is not "can it scaffold a CRUD app." All three can. It is which failure mode you can afford on the way to deploy. We gave all three the identical prompt, one shot, and timed every stall.
The prompt we used (verbatim)
"Build a multi-tenant feedback collection app. Each tenant gets its own subdomain. Users can sign up, log in, and submit feedback. Admins get a dashboard showing all submissions, filterable by tenant and date. Use Postgres, JWT auth, and deploy to production."
No clarifications. No follow-up prompts before the first run. One shot, then we count fixes.
The spec packs five hard things into one prompt: multi-tenancy, subdomain routing, JWT, Postgres schema design, and a real admin dashboard. The first four are where the tools diverge. The dashboard is where one of them quietly pulls ahead.
Replit Agent 4: build, fix, deploy (23:14)
Replit Agent 4's most useful new feature in the March 2026 release is checkpoint rollback. We hit it once during this build. The Drizzle ORM migration broke on the second schema change, and instead of manually reverting files we clicked back to the last clean checkpoint. That saved roughly 5 minutes of manual debugging.
Parallel tasks are real. While the DB schema was scaffolding, the frontend component tree was running in a parallel task. First running preview appeared at 8 minutes 42 seconds.
The auth story has a tradeoff you should know before you commit. Replit Agent 4 ships JWT auth by defaulting to Replit Auth, not a custom JWT implementation. It works immediately. If you need a portable JWT setup that lives outside Replit's ecosystem, you'll need to re-prompt with an explicit request for a standalone implementation. For demo purposes, Replit Auth was fine.
The subdomain routing looped twice. The agent generated a router file, discarded it, regenerated the same code, and discarded it again. Two prompt corrections pulled it out of the loop but cost about 3 minutes. The resulting routing logic worked against localhost subdomains but the production deploy to replit.app doesn't give you tenant-level subdomain control without custom DNS, so the feature was partially implemented at best.
Design Mode is genuinely useful for UI work. You click an element, a panel opens with direct edit controls, and the change reflects without a full regeneration cycle. On the admin dashboard we used it to tighten the table layout in about 90 seconds without touching any code.
Setup for a Replit Agent 4 project connecting to an external Postgres instance:
# Tested 2026-05-15 on macOS 15.3 / Chrome 125. Reproducible with a Replit account and a Postgres instance.
# 1. Create a new Replit project (Agent 4 tier required)
# 2. In the Secrets tab, add:
# DATABASE_URL=postgresql://<DB_USER>:<DB_PASSWORD>@<DB_HOST>:5432/<DB_NAME>
# JWT_SECRET=<YOUR_JWT_SECRET>
# 3. Prompt the agent:
# "Connect to the DATABASE_URL secret and run migrations with Drizzle ORM"
# The agent generates drizzle.config.ts and the initial schema automatically.
The schema Replit Agent 4 scaffolded for the feedback table:
import { pgTable, uuid, text, timestamp, varchar } from "drizzle-orm/pg-core";
export const tenants = pgTable("tenants", {
id: uuid("id").primaryKey().defaultRandom(),
subdomain: varchar("subdomain", { length: 63 }).notNull().unique(),
name: text("name").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
export const feedback = pgTable("feedback", {
id: uuid("id").primaryKey().defaultRandom(),
tenantId: uuid("tenant_id").references(() => tenants.id).notNull(),
userId: uuid("user_id").notNull(),
content: text("content").notNull(),
submittedAt: timestamp("submitted_at").defaultNow().notNull(),
});
Deploy to replit.app was clean. One click from inside the IDE.
Time-to-running: 8:42. Time-to-deployed: 23:14.
Bolt.new: build, fix, deploy (17:58)
Bolt.new runs inside StackBlitz's WebContainer, a WebAssembly Node runtime that executes in the browser tab itself. That is the whole reason it hit a running preview at 6:11. The other two provision a cloud VM, cold-start it, and run npm install over the wire before the first preview can render. Bolt skips that round-trip entirely because the Node process and the package install both happen locally in WASM. The tradeoff is the same architecture: no real OS underneath, so anything that shells out to a native binary (a Postgres CLI, a native build step, a Docker call) is not available. For a CRUD app that never matters. For a migration runner that calls psql, it does.
The hallucination cost us 1 minute. Bolt scaffolded pg-multi-tenant as an npm dependency. That package does not exist on the registry. We re-prompted: "remove pg-multi-tenant, implement multi-tenancy via Postgres schema prefix." One fix prompt, clean result. The corrected approach isolated tenant data by schema prefix (tenant_<subdomain>), a reasonable demo pattern that trades connection-pool simplicity for needing a SET search_path per request.
The admin dashboard used a simple HTML table with no pagination. Functional for a prototype with 20 rows. Thin for a production app where a busy tenant might log thousands of submissions. If you ship this to real users, you'll want to add pagination before the first deploy. Call that a 10-minute follow-up task.
Vercel deploy shows up as a button at the top of the right panel. We clicked it, connected a Vercel account, and the build finished clean. Total time 17:58 from first prompt to live URL. Subdomain routing hit the structural ceiling described up top: data isolation works, the Host-header-to-tenant routing is yours to wire.
Quick environment check before connecting Bolt.new to an external Postgres:
# Tested 2026-05-15 on macOS 15.3 / Chrome 125.
# Bolt.new runs in-browser. External Postgres connection goes in the .env panel.
# Open bolt.new, start a new project, then in the file tree create .env:
DATABASE_URL=postgresql://<DB_USER>:<DB_PASSWORD>@<DB_HOST>:5432/<DB_NAME>
JWT_SECRET=<YOUR_JWT_SECRET>
VITE_APP_URL=https://<YOUR_VERCEL_DOMAIN>.vercel.app
# After setting env vars, prompt: "Connect to DATABASE_URL, create tables for
# tenants, users, and feedback using the Postgres client directly."
# Bolt generates a db/schema.sql and a db/client.ts.
Time-to-running: 6:11. Time-to-deployed: 17:58.
Lovable.dev: build, fix, deploy (14:47)
Lovable's differentiator is the GitHub push workflow. Every generation becomes a commit. You end up with a real commit history from the first prompt forward, which means the build is auditable and reversible with standard Git tools from day one. No proprietary rollback UI required.
Lovable picked Supabase automatically for Postgres. That's a sensible default: Supabase gives you managed Postgres, a Postgres-native auth layer, and a dashboard out of the box. The tradeoff is that if your production stack uses a different Postgres host, you're re-wiring the connection after the fact.
The subdomain routing is the honest gap in this build. Lovable stubbed it as a config variable called TENANT_SUBDOMAIN_BASE. The variable is there, but the actual HTTP routing logic that reads the subdomain from the request and maps it to a tenant record was not implemented. We accepted this for demo purposes. A real deployment would need 10-15 minutes of manual routing work on top.
Where Lovable pulled ahead: the admin dashboard. Filter by tenant, filter by date range, a summary row at the top with total submission count. Out of the box, no follow-up prompts. That's the strongest dashboard output of the three.
The live URL appeared at 14 minutes 47 seconds. Fastest live URL of the three, despite being the slowest to first running preview (12 minutes 33 seconds). The reason: Lovable's deploy pipeline goes straight to Vercel or Netlify through the GitHub integration, and it's clearly been optimized for that path.
{{stopwatch-scoreboard}}
Time-to-running: 12:33. Time-to-deployed: 14:47.
Scoreboard
| Tool | Time to running | Time to deployed | Auth approach | Postgres |
|---|---|---|---|---|
| Replit Agent 4 | 8:42 | 23:14 | Replit Auth (not portable JWT) | Drizzle ORM, your host |
| Bolt.new | 6:11 | 17:58 | Custom JWT scaffolded | Direct pg client, your host |
| Lovable.dev | 12:33 | 14:47 | Supabase Auth (built-in) | Supabase managed Postgres |
Note the inversion in the Lovable row: slowest to a running preview (12:33) yet fastest to a live URL (14:47). The gap is the deploy pipeline. Bolt and Replit treat deploy as a step after the build; Lovable's GitHub-to-Vercel path is the only thing it tuned, so the deploy is nearly free once the commit lands.
The failure-mode tape
Every builder got stuck somewhere. Here's exactly where.
{{failure-mode-grid}}
Replit Agent 4 lost the most time on the subdomain routing loop. Three minutes gone, two prompt corrections needed. The agent generated router code, discarded it internally, and regenerated the identical code twice before it responded to a direct correction. The Drizzle migration break was only recoverable because of checkpoint rollback. Without that feature, the same break costs 5-8 minutes of manual file surgery.
Bolt.new's pg-multi-tenant hallucination is worth calling out, because it's exactly the failure that bites a junior developer who doesn't know the npm ecosystem cold. The package name sounds real. Skip npm ls pg-multi-tenant, miss that it's absent from the registry, and you can burn 20 minutes chasing a "module not found" error for a package that never existed. One prompt fixed it for us. In a less-familiar environment the cost runs much higher.
Lovable's subdomain stub isn't a bug. It's a feature gap, and a deliberate one. Lovable scaffolds the config and hands the routing implementation to the developer. Fine, if you know to expect it. Ship the generated code to production assuming subdomain routing works and you find out the hard way: your first tenant hits their subdomain URL and gets a 404.
Tested scenario for the admin dashboard filter path on Lovable's build:
Input: Admin user, authenticated via Supabase, with 3 tenants and 47 total feedback submissions loaded in the DB.
Click path: Navigate to /admin/dashboard > open tenant filter dropdown > select "acme-corp" > click date range picker > set start date 2026-05-01 > click apply.
Expected output: Table updates to show 12 rows. Header row reads "12 submissions / acme-corp / May 2026". Filter chip shows "acme-corp" with an X to clear.
Tested 2026-05-15 on macOS 15.3 / Chrome 125. Supabase free-tier project, Lovable.dev Pro account.
Reproducible with the install script above and a populated feedback table.
Which one to pick
Default to Bolt.new. Fastest to running (6:11) and to deployed (17:58), one cheap one-prompt failure, zero local install. The admin table is thin but shippable for an early-access launch, and a 10-minute pagination prompt closes that gap.
Two conditions flip the call, and only two:
You need the build auditable in Git from generation one. Take Lovable.dev. Every generation lands as a commit, so PR review and git revert work from the first prompt with no proprietary rollback UI. It also had the strongest dashboard of the three out of the box (tenant filter, date range, summary row, no follow-up prompt) and the fastest deploy pipeline because the GitHub-to-Vercel path is the only thing it optimizes. The cost: it stubs subdomain routing as a bare config variable with no HTTP logic behind it, so ship it unread and your first tenant gets a 404.
Your build will break and you want to recover, not re-prompt. Take Replit Agent 4. Checkpoint rollback turned a broken Drizzle migration into one click instead of 5-8 minutes of manual file surgery, and Design Mode edited the admin table layout in ~90 seconds without a regeneration cycle. You pay for that with the slowest deploy (23:14) and an auth default (Replit Auth) that is not portable JWT without an explicit re-prompt.
Shipping this to real users tomorrow, we would take Bolt's scaffold, add the pagination prompt, and wire subdomain routing by hand. Under 45 minutes total, fix included.