Fix Inngest 401s on Vercel (2026)

Akshit Ahuja

Akshit Ahuja

Co-Founder & Lead Engineer

February 20, 2026
#Inngest#Vercel#Next.js#Deployment Protection#Background Jobs#Webhooks#DevOps

Intro

If your Next.js app is on Vercel and you add Inngest, it works great locally. Then you deploy, click a button that should fire an event, and nothing happens.

You open the Inngest dashboard and see retries. Or worse, you see your functions stuck in “scheduled” forever because the Inngest cloud can’t reach your /api/inngest endpoint.

The log line is usually boring:

- 401 Unauthorized

- 403 Forbidden

- 302 to a login page

This post is the fix. Not “check your env vars” generic advice. The real culprit in 2026 is often Vercel Deployment Protection.

The exact failure mode (what you will see)

When Deployment Protection is on (Standard Protection or All Deployments), Vercel requires auth for basically everything, including middleware and route handlers.

That includes the endpoint Inngest calls to run your functions. In most Next.js setups it is one of these:

- /api/inngest

- /api/inngest (App Router route handler at app/api/inngest/route.ts)

So Inngest sends an HTTP request, and Vercel responds with an auth challenge. Inngest does not have your Vercel cookie. It never will.

Typical symptoms we’ve seen rescuing apps for US and UK founders:

- Inngest shows HTTP 401 or 403 errors in runs

- Your app still responds to real users on the custom domain, but background work is dead

- Preview deployments work, production fails (or the reverse)

- Your Inngest function never starts, so retries pile up and your backlog looks haunted

Why this happens (Deployment Protection is not just “a login wall”)

Vercel’s docs are blunt: deployment protection requires authentication for all requests, including middleware.

That means even “internal” server to server traffic gets blocked unless it brings the right bypass token.

Here’s the gotcha: lots of teams enable protection after a security review, then forget that Inngest, webhooks, and cron-style callbacks are not browsers.

If you are a founder in the US, this usually happens right after you:

- add a staging environment for a client demo

- lock down previews so competitors can’t snoop

- turn on Vercel Authentication for production because you have a healthtech or fintech vibe going

You did the right thing. You just broke your background jobs.

The fast fix in 2026: Protection Bypass for Automation

Vercel has an official escape hatch called “Protection Bypass for Automation”. It gives you a secret value. If requests include it, Vercel skips the protection checks.

You can send that bypass secret in two ways:

- Header: x-vercel-protection-bypass: <secret>

- Query param: ?x-vercel-protection-bypass=<secret>

Header is better. Query param is for third party webhooks that cannot set headers.

Now the key point for Inngest:

Inngest has a Vercel integration and settings where you can add the deployment protection key so Inngest can reach your protected deployment.

Inngest’s Vercel deploy docs call this out too: either disable deployment protection, or configure protection bypass.

Step-by-step (takes 30 to 90 minutes)

1) Turn on Protection Bypass for Automation in your Vercel project

- Go to the project’s Deployment Protection settings

- Enable “Protection Bypass for Automation”

- Copy the secret (Vercel also sets VERCEL_AUTOMATION_BYPASS_SECRET on new deployments)

2) Add the bypass secret to Inngest

- Open the Inngest dashboard

- Go to Integrations -> Vercel

- For your project, paste the deployment protection key

3) Redeploy your Next.js app (yes, do it)

The bypass secret is attached to deployments. If you rotate it, old deployments won’t magically start working. Redeploy so everything is aligned.

4) Verify with a dumb curl

Hit your deployed endpoint from a terminal:

curl -i https://YOUR_DEPLOYMENT_URL/api/inngest

If it returns an auth challenge, you are still blocked.

If you include the header:

curl -i -H "x-vercel-protection-bypass: $VERCEL_AUTOMATION_BYPASS_SECRET" https://YOUR_DEPLOYMENT_URL/api/inngest

You should get a 200 or at least something that looks like your route handler, not a login interstitial.

The sneaky second cause: your own Next.js middleware

We see this a lot: teams fix Vercel protection, and it still fails.

Why? Because their own middleware is acting like a bouncer.

Common patterns:

- A middleware matcher like /((?!_next/static).*) that catches everything

- An auth library that redirects any unauthenticated request to /login

- A “protect all /api routes” rule because someone got spooked by bots

So Inngest hits /api/inngest, and your middleware returns a 302.

Inngest is not a browser. It follows redirects for a bit, then marks the attempt as failed.

Fix: carve out a hard exception

You want /api/inngest to behave like a webhook endpoint.

Practical rule:

- If pathname starts with /api/inngest, skip middleware auth and return next

Also make sure you are not doing fancy stuff like rewriting /api/* to a different host when protection is on.

The canonical URL trap (vercel.app vs custom domain)

Another ugly 2026 issue: your app “works” in the browser, but automation hits a different hostname.

Example:

- Users hit https://app.yourdomain.com

- Your Inngest sync is pointing at https://your-project.vercel.app

If Standard Protection is enabled, Vercel might protect the generated deployment URL more aggressively than your custom domain.

So you get a split brain:

- Humans are happy

- Jobs are dead

Pick one canonical domain for automation.

If you are serving EU customers and care about data locality, pick the domain that routes to the region where your database lives. Latency matters more for background jobs than most people admit.

What this costs (real numbers)

For a typical early stage SaaS:

- Time: 0.5 to 2 hours to diagnose and fix

- Cost: usually $0 extra if you already have Vercel Pro

Where people lose money is the delay, not the fix.

We’ve seen:

- Signup emails not sending for 2 days

- CSV imports stuck, so paid users churn

- Billing reconciliation jobs missing, so you spend a Friday night doing spreadsheets

If you’re in the US and you do B2B, this can kill a deal. A buyer will not forgive “our background jobs were down” when they are evaluating your reliability.

A small production hardening plan (so this doesn’t happen again)

I’m opinionated here: don’t stop at “it works”. You want it to keep working during the next emergency deploy.

1) Make your Inngest functions idempotent

Even when protection is fixed, Inngest can retry. If your function charges a card, creates an invoice, or sends an email, retries can hurt.

Do this:

- Use an idempotency key in Stripe calls

- Use unique constraints in Postgres for “only once” inserts

- Record an event id in a table and ignore repeats

Rule of thumb: if a job can cost money, assume it will run twice at least once in production.

2) Keep a dead simple health check

Add an endpoint that does one thing:

- returns 200

- does not touch the database

- is not behind auth

Then monitor it.

If you’re a founder in Canada or Australia running lean, this is the cheapest monitoring you’ll ever set up.

3) Add alerts where it hurts

Don’t alert on “any job failed”. That just trains you to ignore alerts.

Alert on:

- retries above a threshold in 10 minutes

- a specific business workflow failing (billing, onboarding, report generation)

Even a Slack webhook is fine. You just need a flashlight before the house burns down.

4) Keep secrets out of logs

Bypass tokens are secrets. Treat them like Stripe keys.

Stuff that leaks secrets in real life:

- printing request headers in middleware logs

- logging the full webhook URL (with query params) in a load balancer

- dumping “all env vars” in a debug endpoint (yes, teams still do this)

If you must use query params, strip them in logs.

Quick troubleshooting flowchart (works every time)

1) Is Inngest getting a 401/403?

- If yes, check Vercel Deployment Protection and bypass.

2) Is it getting a 302 or HTML?

- If yes, check your middleware and redirects.

3) Is it hitting the wrong hostname?

- If yes, fix the Inngest app URL to the same domain your users use.

4) Still stuck?

- Temporarily disable protection for 5 minutes. If everything instantly works, you’ve confirmed the root cause. Turn it back on and fix properly.

When you should NOT use bypass tokens

If you can avoid protecting production in a way that blocks machine traffic, do that.

Bypass tokens are fine, but they are still secrets. They leak through logs more often than teams admit.

Safer patterns:

- Keep production public, protect only preview deployments

- Restrict admin pages with app-level auth, not Vercel auth

- Put sensitive internal tools behind SSO or a VPN, not behind your whole deployment

If you are in fintech or healthtech and you must protect production URLs, then use bypass tokens, rotate them, and lock down who can view them.

Quick recap

- Inngest needs to call your /api/inngest endpoint.

- Vercel Deployment Protection can block that with 401/403 or redirects.

- Fix it with Protection Bypass for Automation and add the bypass key in the Inngest Vercel integration.

- Then harden: idempotency, middleware exceptions, and a single canonical URL.

If you’re stuck and your backlog is piling up, this is exactly the kind of “small bug, big blast radius” thing we fix for founders.

---

Related reading

Akshit Ahuja

Akshit Ahuja

Co-Founder & Lead Engineer

Software EngineerBackend Specialist

Backend systems specialist who thrives on building reliable, scalable infrastructure. Akshit handles everything from API design to third-party integrations, ensuring every product HeyDev ships is production-ready.

Related Articles