I keep hearing the same story from people who built something real with Cursor, Lovable, Bolt, v0 or Replit: the app exists, the demo works, and it has been "almost ready" for two months.

The 20% they are missing is rarely a feature. It is a set of integration seams that a generator will happily write code around and never solve. Here are the nine that block launches most often, in the order I check them, with the symptom and the fix.

1. Sessions that only exist in memory

Symptom: you can log in, and a refresh logs you out. Or you can log in on desktop and not on the deployed domain, but it works on localhost.

What's happening: the auth code stores a token in a module-level variable, or sets a cookie without Secure/SameSite, or signs with a secret that is regenerated on each cold start because it is generated at boot instead of read from the environment.

Fix: persist the session in an HttpOnly, Secure, SameSite=Lax cookie (or a refresh token in storage for mobile), keep SESSION_SECRET in the environment, and test after a hard reload, a tab restore, and a cold start. If your serverless function signs the token, it must use a stored secret — the same one, every time.

2. Auth that trusts the client

Symptom: everything works, and any user can read another user's records by changing an id.

What's happening: the generated code checks if (user) in the UI and never checks ownership on the server. With a hosted database, the row-level rules were never written at all.

Fix: every read and write on the server (or in the database rules) must be scoped to the authenticated subject. Not WHERE id = $1 but WHERE id = $1 AND user_id = $subject. On Postgres with row-level security, the policy is the product; test it with two accounts, not one.

3. Payments that only pass in test mode

Symptom: Stripe checkout redirects and returns, but the order never appears, or appears twice, or appears in test mode and not in live mode.

What's happening: the "success" page is treated as proof of payment. No webhook, no signature verification, no idempotency key.

Fix: the redirect page is for the user, not for the database. Grant access in a webhook handler that verifies the signature against the raw body, and write the event id before doing anything so a retried delivery cannot double-credit. Test with the Stripe CLI, then in live mode with a real card and a real refund.

4. Environment variables that only exist on your machine

Symptom: the deploy builds, then the first request that touches a third-party API returns 401 or undefined.

What's happening: .env is not committed (good), the platform's environment is empty (bad), and the code fails at the first network call instead of at boot.

Fix: validate the environment at startup and crash loudly if something is missing. Keep a .env.example in the repo. Treat "works locally" as unverified until it works on the deployed URL.

5. Database schema without migrations

Symptom: you changed a column two weeks ago and the deployed database does not have it. Nobody knows what the live schema is.

What's happening: the schema was applied by hand, or by a generator that ran once.

Fix: one source of truth, applied by a migration tool, run automatically in deploy. Seed data separate from schema. This is also the step that makes a staging environment possible at all.

6. CORS, cookies and the domain triangle

Symptom: the API works from localhost:3000 and fails from https://app.yourdomain.com with a CORS error or a dropped cookie.

What's happening: the API allows *, and a wildcard origin cannot carry credentials. Or the cookie was set on the API's host and the front end lives on another.

Fix: allow-list exact origins, credentials: include on the client, Access-Control-Allow-Credentials: true plus an explicit origin on the server, and put front end and API on the same registrable domain when you can.

7. Deploy that is not a deploy

Symptom: the preview URL works, the custom domain shows an old build, www and the apex behave differently, and half the traffic is HTTP.

What's happening: DNS records were added once and never verified, the platform is serving a cached build, and SSL was issued for one hostname only.

Fix: decide the canonical host, redirect everything else to it, force HTTPS, verify both apex and www, and check a hard reload on a phone on cellular data — not just your laptop on the same network.

8. No error visibility

Symptom: a user says "it broke". You have nothing. No stack trace, no request, no timestamp.

What's happening: generated code has console.log and no error boundary, no server logging, no alert.

Fix: a client error boundary that reports, server logging with request ids, and one alert channel you actually read. You cannot operate what you cannot see, and "operate" is the difference between a demo and a product.

9. Mobile reality

Symptom: fine in a desktop browser, broken on a phone: keyboard covers the input, fixed footers overlap the content, 100vh is wrong, taps are 12px tall.

What's happening: layout was never checked on a device. 100vh was used instead of dynamic viewport units, and safe areas were ignored.

Fix: test on a real phone with the keyboard open. Use dvh, env(safe-area-inset-*), and touch targets of at least 44px. Then test a slow connection, because your users are not on your Wi-Fi.

If the product is a mobile app, add a tenth

Store review is its own integration seam: privacy manifest, permission strings, a real account-deletion path, and a build that does not depend on a debug keystore. Most rejections I see are not about the product at all.

Why generated code stalls exactly here

A generator is excellent at the parts that are visible in a single file and weak at the parts that span files, environments and time: secrets, webhooks, migrations, domains, ownership checks. None of those are hard individually. All of them are invisible until you try to ship, and each one looks like "just one more bug".

That is why the honest answer to "how long until launch?" is not a feature list. It is a checklist of seams, each verified in the environment it will actually run in.

I do this for a living now. I take over half-finished AI-generated codebases as they are, run a free review against this list, and quote only the work that is actually blocking launch — then finish it through deploy and store release, usually in three to five days.

If you only take one thing from this: stop asking "what feature is missing?" and start asking "which seam has never been verified outside my laptop?" That question is what a launch is made of.