Key takeaways
A vibe-coded SaaS is not production-ready because the demo works. It is ready when twenty boring gates can fail the release.

It is 11:40 p.m. in Pune. The first paid tenant joins at nine. Login works on your laptop. The test card works. You have not checked whether tenant A can read tenant B, whether the OpenAI key is in the client, or whether anyone can turn the model off if a loop starts.

I have sat in that room. The instinct is to polish the empty state. The work is to run a gate list that does not care how the landing page looks.

That night is why I keep a written benchmark. Not a vibe. A folder of checks that can fail.

The problem a green preview hides

AI-built SaaS products fail in familiar ways. The preview is public. The client holds a secret. The database trusts the browser. The model has no budget. CI is a screenshot in Slack. Nobody has deleted a user end to end.

I opened one of these stacks in Ahmedabad the week a founder wanted invoices on. The app looked finished. The service role key was in the bundle. Row security was off. The “forgot password” mail printed the reset token in the server log. None of that shows up in a Loom.

According to the OWASP project, broken access and leaked secrets are not advanced topics. They are the first two ways a stranger becomes your most active user. Data from the GDPR.eu site is just as plain. If you cannot find, export, and delete a person’s data, you are not ready for a European card, and you are not ready for a careful Indian one either.

Why the usual advice fails the night before launch

The usual advice is a list of tools. Add auth. Add tests. Add a cookie banner. The founder adds a library, ticks a box, and ships. The library does not enforce a session on the preview URL. The banner does not delete a row. The test file is not in CI.

Standard checklists also assume you wrote the code. Vibe-coded apps were assembled by a model that will happily skip RLS because the prompt said “make the table load.” A benchmark has to assume the generator omitted the boring part.

That is why IndiaNIC keeps a Production Gate: twenty checks, each with a fail mode you can see. We do not ask whether you installed a thing. We ask what happens when it is missing.

Clipboard checklist and black pen on a white desk with a laptop corner in soft blur
Twenty boxes. None of them are optional if customers will pay.

The IndiaNIC Production Gate

This is the list I walk with a founder. Use it as a release gate, not as a mural. If a row fails, the release waits. Next.js documentation at nextjs.org/docs will tell you where routes and env files live. It will not tell you whether you are ready to take money.

#CheckFail mode
1Session on every mutating routePreview URL is a public write API
2Session expiry and a real logoutStolen cookie never dies
3Row Level Security on tenant tablesTenant A reads tenant B
4Service role key server-onlyBrowser can dump the database
5Secrets absent from git historyOld commit still holds keys
6Indexes on tenant filtersFirst real load freezes queries
7Per-user API rate limitOne loop spends the month
8Provider spend capCard dies at 3 a.m.
9Model calls on a queueRefresh starts a new completion
10CORS and CSRF lockedAny site can call you
11CI on every pull requestMain is an untested vibe
12Playwright on auth and payLogin 500s after deploy
13Logs stripped of personal dataSupport paste becomes a breach
14Data deletion pathYou cannot honour a request
15Backup restore drillBackup exists, restore does not
16Error tracking wiredCustomers report what you missed
17Dependency audit in CIA known CVE is live
18IP assignment on fileYou do not own what you sell
19Feature flags on model changesA bad prompt hits everyone
20Kill switch and on-callNobody can stop the model
A product that cannot fail a check cannot pass one either.

Why is a twenty-point gate better than a tool list?

A twenty-point gate is better than a tool list because each row names the failure a paying customer will feel, not the library you meant to install. Auth, RLS, cost caps, CI, and GDPR show up as fail modes you can demo. A tool list lets you tick “added Supabase” while tenant A still reads tenant B.

I would rather ship late with a red row than ship on time with a quiet leak. The gate is the argument I use when a founder wants to “add it next week.”

What does an IndiaNIC benchmark review actually produce?

An IndiaNIC benchmark review produces a scored folder: each of the twenty gates marked pass, fail, or not applicable, with the exact file or dashboard that proves it. Founders get a repair order, not a slide. The review is the same walk we would do the night before that first paid tenant.

We do not invent a score out of one hundred. We list the red rows. You fix those. Then we walk it again.

Do not take a paid tenant on a preview URL. Put auth in front, turn RLS on, and confirm the secret key is not in the bundle. The landing page can stay ugly. The gate cannot stay open.

How we applied the gate on that Pune night

We did not polish copy. We walked the list from the top. Auth was a cookie that never expired. RLS was off. The OpenAI key was in a client chunk. There was no rate limit. CI was a memory.

By morning we had a session that died, policies on the two tenant tables, a server route for the model, and an Upstash limiter. We hung GitHub Actions on a Playwright login. We wrote down how to delete a user. Stripe’s own key documentation and GitHub’s secret scanning docs were the rehearsal scripts, not a new framework.

The tenant still joined at nine. They joined a product that could fail a check. That is the only kind I will put a card against.

I keep more of these field notes on the IndiaNIC blog. The useful ones are the lists you can run without me in the room.

If you want one move tonight, run rows 1, 3, 4, 7, and 14. Those five decide whether morning is a launch or an apology.

I keep a printed copy of this list on the wall of the hardening room in Ahmedabad. It is not decoration. When a founder says “we are basically production ready,” we walk the wall. If more than four boxes are empty, we do not argue about launch dates. We pick the empty boxes that can take money or data, and we close those first.

The checklist is a conversation tool as much as an engineering artefact. Finance can understand “the model can spend without asking.” Legal can understand “we cannot say where the files live.” You do not need every stakeholder to read a pull request. You need them to see which boxes are still red.

Frequently asked questions

Which five checks should I do the night before a first customer?

The five checks the night before a first customer are session auth on writes, row security on tenant tables, no privileged key in the browser, a per-user rate limit on model calls, and a delete path you have actually run. Those five stop the common apology. The other fifteen still matter. They can wait until the afternoon if morning is already booked.

Do them in that order. A pretty CI badge will not save a public write API.

Is Row Level Security enough without auth on the API?

Row Level Security is not enough without auth on the API, because RLS needs a user identity the database can trust. A wide-open route that uses a service role key bypasses every policy. Put a session on the route, use the user’s connection or a scoped token, and keep the service role on the server. Then the policies have someone to apply to.

I have watched a “we turned RLS on” demo fail in one curl. The route was still admin.

How often should I rerun this checklist?

Rerun this checklist on every release that touches auth, data, spend, or the model, and once more after any generator prompt that rewrote a route. Vibe-coded apps regress when a prompt “simplifies” a file and drops a policy. A monthly walk is fine for quiet weeks. A prompt that touches the server is not a quiet week.

The 2026 bar I hold is simple. If a customer will pay, all twenty boxes get a real answer.