Vibe coding does the thing it was built to do very well. You describe an app, a few minutes later it exists, and you can send someone a link to it. For getting an idea out of your head and in front of a person, nothing else is close.
The problems turn up later, when other people start depending on it. Getting an app to run and getting an app ready for other people to depend on are two separate jobs, and the second one is almost entirely invisible from inside the builder. The screen looks the same either way.
Three of them come up over and over, and they’re the ones people get stuck on. All three live outside the app itself, in hosting, in DNS and in how keys are handled, so going back to the builder and asking it to fix the problem doesn’t get you anywhere. The code it wrote is fine. There’s just nowhere obvious to look next.
1. It goes offline
You send someone the link, they open it a week later, and the site is down. Or it takes fifteen seconds to load a page that was instant when you built it.
Most of the time the app is still published on a subdomain of the builder, running on the builder’s infrastructure and paid for out of the builder’s plan. For a prototype that’s a good trade. Once the app matters, it means your uptime depends on the platform’s uptime, on how many credits you have left, and on whatever the company decides to change this quarter.
The other common cause is a free database tier that pauses itself. Most free plans suspend a project after a stretch with no traffic, and the first visitor after that either waits for it to wake up or gets an error, because the app was written assuming the database is always there. You never saw it during testing, because you were the only person using the app and you never left it alone for long enough.
The fix for both is to move the app onto hosting you pay for, with a database that stays awake, and to put a monitor on it so you’re not relying on a user to tell you it’s down. That’s a post on its own: how to stop your Lovable app going offline.
2. The custom domain half-works
Most of the time this goes fine. You buy yourcompany.com, paste it into the builder, wait a bit, and it works. It’s on this list because of what happens the rest of the time, when the site loads for you and not for a friend, or loads and then shows a certificate warning that makes people close the tab. At that point there’s nothing to click on and nothing in the app to fix, and a launch can sit blocked for weeks over it.
It’s nearly always DNS. Pointing a domain at an app means adding a record at your registrar, usually a CNAME for www and either an A record or an ALIAS for the bare domain, and then waiting for that change to propagate. Propagation can take ten minutes or most of a day depending on the TTL on the old records. If you add a record in the wrong place, or leave a record from a previous host in place, you get the half-working state where some people reach the new app and some reach whatever was there before.
The certificate warning is the same problem wearing a different hat. The padlock comes from a certificate your host requests automatically, and it can only be issued once the domain resolves to the host. A DNS mistake therefore shows up as a security warning a few minutes later, which sends people looking in the wrong place.
DNS is unforgiving rather than complicated. The feedback loop is slow, and a record that’s wrong looks exactly like a record that hasn’t propagated yet, which is what makes it so hard to debug from the outside. Change one record at a time, confirm it has resolved before you touch the next, and resist the urge to change three things at once because nothing seems to be happening.
3. Anyone can read your API keys
This is the one I would fix first, because you can’t see it from the outside and it costs real money.
Your app needs keys: one for the database, one for whichever AI API it calls, one for the email provider, one for payments. A key is a password. It works for whoever is holding it. AI builders will put a key wherever it makes the app work, and quite often that place is the browser, where every visitor can read it out of the page source or the network tab. Somebody who finds an OpenAI or Anthropic key in your front-end code can run up a four-figure bill on your account in an afternoon.
The distinction that matters is between a secret and an environment variable, and the builders aren’t clear about it. An environment variable is any named value your app reads at runtime instead of having it typed into the code. Some of those values are fine to expose, like a public analytics ID. Some of them are the keys to your database. What decides which is one thing only: whether the value is read on the server, where nobody can see it, or in the browser, where everybody can. In most frameworks the browser-visible ones carry a prefix such as PUBLIC_ or VITE_, so a real secret with one of those prefixes is being handed to every visitor.
Go and find out which of your keys the browser can see, then move those calls to the server and reissue the keys. Keeping your vibe-coded app secure walks through how.
Where to start
In all three cases the app itself is fine. It runs, and it did the thing in the demo. What’s missing sits in the layer underneath: where the app runs, how people reach it, and what it hands out to anyone who looks. That’s a separate job from building, and a much duller one, so most people have never had a reason to learn it.
If you want to work through it yourself, start with the keys, because that’s the one with a bill attached, and then move the app onto hosting you control, which deals with the first problem and most of the second.