Vercel has enabled Deployment Protection on new projects by default since November 2, 2023. That single fact makes most of the "your Vercel preview URLs are wide open" advice on the internet, including the earlier version of this page, about three years out of date.
The advice is not harmless. It sends people hunting for a setting that is already on, while the thing that actually leaks their data sits in a build output nobody looked at.
TL;DR
Vercel's platform security is strong and its defaults got better in 2023: new projects ship with Vercel Authentication protecting preview and deployment URLs, on every plan including Hobby. What still leaks is yours, not theirs. NEXT_PUBLIC_ variables go to the browser and no setting stops that, a custom domain on a preview branch quietly loses its noindex header, and projects created before November 2023 were never migrated.
What Vercel Handles For You
The platform layer is genuinely solid, and it is worth being specific about which parts you can stop worrying about.
Handled by the platform
- HTTPS on every deployment, including generated
.vercel.appURLs - Environment variables encrypted at rest, server-only unless you opt out
- Each serverless function runs isolated, with no access to another's memory or filesystem
- DDoS protection on all plans, Hobby included
X-Robots-Tag: noindexset automatically on previews and stale production deploys- Deployment Protection on by default for projects created after November 2023
Still yours to get wrong
NEXT_PUBLIC_variables, which no platform setting can save you from- Authorization inside API routes, which Vercel does not write for you
- Custom domains pointed at preview branches
- Any project created before November 2023 and never migrated
The Preview-URL Warning Is Out Of Date
Here is what actually changed. Vercel's changelog entry, Deployment Protection is now enabled by default for new projects, published November 2, 2023, made Vercel Authentication the automatic default for new projects. Vercel Authentication restricts access to logged-in Vercel users with rights on the project, and per Vercel's Deployment Protection docs it is "Available on all plans".
The scope that ships by default is Standard Protection, which covers every deployment URL except your production domain. Which is the correct shape: your production site is supposed to be public.
So if you created a Vercel project any time in the last three years, opened it up, and found protection already enabled, nothing is broken. That is the default working.
The gap the changelog admits to. The change applied to new projects only. Vercel's own wording points existing users at a migration guide rather than flipping anything for them. If your project predates November 2023 and nobody has touched the Deployment Protection settings since, your previews are still open, and they have been open the whole time.
Checking takes ten seconds. Open the project, go to Settings, then Deployment Protection, and look at whether the scope is Standard Protection or None.
Three cases the default does not cover
Projects created before November 2, 2023. Covered above. This is the one worth checking today.
Hobby-plan production domains. Vercel's docs are explicit: on Hobby, Standard Protection "protects your preview deployments and deployment URLs, but your production domain remains publicly accessible." Protecting a production domain needs Pro or Enterprise. For a side project this is fine and expected. It is only a problem if you were treating your Hobby production URL as a private staging environment, which some people do.
Custom domains on preview branches. This is the one that surprises people, and it is the most likely way a Vercel preview ends up in Google.
The Custom-Domain Hole In noindex
Vercel sets X-Robots-Tag: noindex on preview deployments and on production deployments that have been superseded. You can confirm it yourself on any preview URL:
curl -sSI https://your-project-git-somebranch-yourteam.vercel.app | grep -i x-robots-tag
# x-robots-tag: noindex
Now assign staging.yourapp.com to that same branch. Vercel deliberately drops the header, on the reasoning that a custom domain on a branch means you intended that environment to be reachable. Vercel's guide puts it plainly: "search engines can now index that domain and its duplicate content."
A branch domain is a published site. The moment you point a custom domain at a preview branch you have two things at once: an indexable public site, and an environment your team still thinks of as internal. Staging databases, seeded test users, debug routes, and half-finished features all become crawlable. If you need the domain but not the indexing, set the header yourself in next.config.js or vercel.json.
Vercel Authentication still applies to that domain under Standard Protection, so a logged-out crawler gets a login wall rather than your app. The failure mode is the project where somebody turned protection off to let a client preview the work, and then never turned it back on.
The Risk No Default Can Fix
Everything above is a setting. This one is not.
NEXT_PUBLIC_ is not a warning label, it is an instruction. Any environment variable prefixed with NEXT_PUBLIC_ gets inlined into the JavaScript bundle at build time and shipped to every visitor who loads the page. Vercel encrypts it at rest, then hands it out in your bundle, because that is exactly what the prefix asks for. There is no dashboard toggle that overrides it.
| Variable name | Where it ends up | Safe for |
|---|---|---|
STRIPE_SECRET_KEY | Server only | Real secrets |
NEXT_PUBLIC_STRIPE_KEY | Server plus every browser | Publishable keys only |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Server plus every browser | Fine, it is designed for this |
NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY | Server plus every browser | Nothing. This is a full database breach |
We see the fourth row in scans more often than we would like. The pattern is consistent: someone hits an environment variable that reads as undefined in a component, adds NEXT_PUBLIC_ to make the error go away, and ships it. The error does go away. So does the boundary between your database and the internet.
Nuxt users get the same trap with a different spelling, NUXT_ENV_. Vite-based apps use VITE_. The prefix changes, the outcome does not.
Audit it from the outside, not the dashboard. Your Vercel environment variable list will not tell you what leaked, because the leak happens at build time. Load your production site, open DevTools, and search the loaded JS for sk_live, service_role, SECRET, and PRIVATE. What you find there is what your visitors already have. Our Vercel security best practices guide walks through the full audit.
What Protection Actually Costs
Advice to "just turn on password protection" skips the price tag, and the price tag is the reason most teams do not have it.
| Method | Hobby | Pro | Enterprise |
|---|---|---|---|
| Vercel Authentication | Included | Included | Included |
| Standard Protection scope | Included | Included | Included |
| Protect production domain | No | Included | Included |
| Password Protection | No | 150 dollars per month add-on | Included |
| Trusted IPs | No | No | Included |
| Passport (your own IdP) | No | No | Included |
Password Protection, private production deployments, and protection exceptions all sit inside Vercel's Advanced Deployment Protection add-on, which costs 150 dollars per month on Pro and carries a 30-day minimum before you can cancel it.
For nearly every team reading this, Vercel Authentication is the right answer and it is free. Password Protection earns its cost in one situation: showing a preview to a client or contractor who does not have a Vercel account.
Our Verdict
Safe to UseVercel is safe to run production on. It publishes SOC 2 Type II compliance (and signs a HIPAA BAA on Pro and Enterprise, though not Hobby: see Is Vercel HIPAA Compliant?), it encrypts secrets at rest, it isolates function execution, and since late 2023 its defaults have been better than the advice written about them.
The honest version of the risk is less dramatic than the preview-URL story and more likely to affect you: a secret you prefixed into your own bundle, an API route with no ownership check, or a project old enough to have missed the default. None of those show up in Vercel's dashboard, which is precisely why they survive.
Is Vercel safe for production?
Yes. Vercel runs the platform layer well: automatic HTTPS, encrypted environment variables, isolated function execution, and DDoS protection on every plan. The risk in a Vercel app is almost never Vercel. It's a secret you prefixed with NEXT_PUBLIC_, a branch you pointed a custom domain at, or an API route with no authorization check in it.
Are Vercel preview deployments public by default?
Not since November 2, 2023. Vercel's changelog states that Deployment Protection with Vercel Authentication is enabled by default for new projects, and Vercel Authentication is available on all plans including Hobby. The catch is that the change wasn't applied retroactively, so a project created before that date is still open unless somebody turned protection on manually.
Can search engines index my Vercel preview deployment?
Normally no. Vercel sets an X-Robots-Tag: noindex header on preview deployments and on outdated production deployments. There's one deliberate exception: if you assign a custom domain to a non-production branch, Vercel omits the header, because it assumes a custom domain means you want that environment reachable. A staging subdomain set up this way can be crawled and indexed.
Are my API keys safe in Vercel environment variables?
They're encrypted at rest and only readable server-side, with one large exception you control. Any variable whose name starts with NEXT_PUBLIC_ is inlined into the JavaScript bundle at build time and shipped to every visitor. No Vercel setting protects you from this, because from the platform's point of view you asked for it. Check your bundle, not your dashboard.
Does password-protecting a Vercel deployment cost extra?
On Pro, yes. Vercel Authentication is free on every plan, but Password Protection sits in the Advanced Deployment Protection add-on at 150 dollars per month for Pro accounts, and it's included on Enterprise. You also have to keep the add-on for at least 30 days before you can cancel. For most teams Vercel Authentication is the setting to use.
Further Reading
- Vercel security best practices for the full audit, headers included
- Vercel security checklist for a pre-launch pass
- Environment variable best practices
Deploying to Vercel?
We check your live bundle for exposed keys, not just your dashboard settings.