Instant rollback patterns when a deployment breaks production.
Production is broken. The first question is not "what caused it" — that's the second question. The first question is: what is the fastest path to a working site? That answer determines everything you do in the next 60 seconds. The decision tree below exists so you don't have to think it through under pressure.
⬡ What you'll build
Four scenarios. Each has one correct first move.
Scenario A: Deployment just went out and the site is broken
The most recent deploy is the problem. Code change introduced a bug, or a new dependency broke something.
→ Vercel instant rollback. Promotes the previous deployment to production without a new build. Fastest path — takes about 60 seconds.
Scenario B: Deployment looks fine but something changed recently that broke it
A configuration change caused the problem — env var was added/removed/changed, Vercel project settings were modified, or a domain configuration changed. The code itself may be fine.
→ Revert the configuration change. Check Vercel's environment variables, check DNS/domain settings. A Vercel rollback will not help here — you'd roll back to the same code running against the same broken configuration.
Scenario C: Deployment succeeded and the build is fine, but a specific feature is wrong
The feature is broken in production but was working before. The code change that caused it may not be in the most recent commit — it could have been introduced several commits ago and only became visible now.
→ git revert + new deploy. Find the commit that introduced the regression, revert it cleanly, push to trigger a new Vercel deployment.
Scenario D: Multiple commits since the last known-good state, broken state is not obvious
You don't know which commit caused the problem. The symptoms could point to any of several recent changes.
→ git bisect first. Identify the culprit commit with binary search, then revert that specific commit. Rolling back blindly risks reverting work that wasn't the problem.
Every Vercel deployment gets a unique URL and is preserved in your deployment history. Promoting a previous deployment to production is instantaneous — Vercel just changes which deployment the production domain points to. No rebuild required.
Via Vercel dashboard:
The broken deployment stays in history. You're not deleting anything. You can re-promote it later if needed.
Via Vercel CLI:
# List recent deployments to find the URL you want to roll back to
vercel ls
# Roll back to a specific deployment
vercel rollback <deployment-url>
# Example
vercel rollback my-project-abc123xyz.vercel.app
What it takes: Roughly 60 seconds from clicking Promote to the production domain serving the previous build.
What Vercel rollback does NOT revert:
Vercel rollback is a code rollback only. Everything else is your responsibility.
git revert creates a new commit that undoes the changes from a previous commit. It does not rewrite history. That distinction matters when you're working with a shared remote repository.
# Step 1: Find the commit you want to undo
git log --oneline -10
# Output:
# a3f9c21 (HEAD -> main) fix: update checkout flow validation
# 7b2e14d feat: add discount code support
# c891a03 fix: correct tax calculation rounding
# 4d12f8a feat: add stripe webhook handler
# ...
# Step 2: Revert the specific bad commit
git revert a3f9c21
# Opens your editor for the commit message — or use --no-edit to accept default
git revert a3f9c21 --no-edit
# Step 3: Push — this triggers a new Vercel deployment
git push
# Vercel picks up the new commit, builds, and deploys
# The bad change is undone; git history is intact
Why not git reset --hard?
# DO NOT do this for a shared production branch:
git reset --hard <previous-commit-hash>
git push --force
# Why it's wrong:
# 1. Rewrites history — anyone who pulled after your bad commit now has
# diverged history. Their next push or pull will be broken.
# 2. The force push destroys the bad commit on the remote — you lose
# the record of what happened, which you need for post-mortems.
# 3. Vercel deployment history may reference the deleted commit.
# git reset --hard is safe only on commits you haven't pushed yet.
# For anything already pushed to a shared branch: always git revert.
Reverting a merge commit:
# Merge commits require specifying the mainline parent
git revert -m 1 <merge-commit-hash>
The -m 1 flag tells git to revert to the first parent (the branch you merged into). This is the correct option when reverting a feature branch merge.
When multiple commits have gone out and the broken state isn't obviously tied to one change, git bisect performs a binary search through your commit history to find the exact commit that introduced the problem.
# Step 1: Start bisect
git bisect start
# Step 2: Mark the current state as bad
git bisect bad
# Step 3: Mark a known-good commit
# Find a commit hash you know was working — yesterday's deploy, last week's tag
git bisect good 4d12f8a
# Git now checks out the commit halfway between good and bad
# Test the site or run the affected code path
# Step 4: Mark each checkout as good or bad
git bisect good # if this state works
# or
git bisect bad # if this state is broken
# Git keeps narrowing — typically 4-6 steps for 50 commits
# When bisect is done, it prints:
# a3f9c21 is the first bad commit
# Step 5: Exit bisect (returns you to HEAD)
git bisect reset
# Step 6: Now you know exactly what to revert
git revert a3f9c21 --no-edit
git push
Bisect is most useful when the failure is subtle — a feature that's wrong, not a crash. For crashes that are obviously tied to the most recent deploy, don't bisect — just rollback directly.
This is the part that will burn you if you don't internalize it.
Database schema changes: If your deployment ran a migration that added or dropped columns, Vercel rollback does not reverse those migrations. Rolling back the code while the database schema has moved forward will either cause runtime errors (code references a column that no longer exists) or behave unpredictably (code doesn't know about a new column the schema added).
Discipline: Do not run irreversible database migrations and feature code in the same deployment. Separate them. Add the column first with a backward-compatible migration, deploy the code that uses it, then optionally remove the old column in a later deploy.
External API calls that already executed: If your code sent emails, charged cards, created records in Stripe or Salesforce, or triggered any third-party webhook — those happened. Rolling back your code doesn't undo them. You will need to handle these manually.
S3 and file storage: Files uploaded, moved, or deleted during the deployment window are not restored by a Vercel rollback.
Email and notifications: Already sent. Rollback does nothing here.
The summary: Vercel rollback is a traffic routing change. It moves your production domain from pointing at deployment A to pointing at deployment B. That's it. Anything that happened in the world while deployment A was live — database writes, external API calls, user-visible side effects — those are permanent.
Before any significant deployment, note these so you can execute a rollback without having to look things up under pressure:
# Note the current production deployment URL
vercel ls
# Copy the URL of the current production deployment — not your domain, the *.vercel.app URL
# Example: my-project-git-main-yourname.vercel.app
# Note the last known-good git hash
git log --oneline -3
# Copy the hash of HEAD (the commit you're about to deploy from)
# If this deployment changes env vars, note the current values
vercel env ls
# Screenshot or copy the current variable values before changing them
# If this deployment runs migrations, document the reverse migration
# before deploying — not after
This takes 2 minutes. Skipping it means a rollback that should take 60 seconds takes 10 minutes because you're searching for the right deployment URL while production is down.
ℹVercel retains 100 deployments on the Hobby plan
Vercel's deployment history is not infinite. The Hobby plan retains the 100 most recent deployments. For a project with active development, that's weeks of history — but if you need to reference a specific deployment from 3 months ago, it may be gone. Before a major release or risky deployment, note the exact deployment URL of your current stable build in your project notes or a commit message. Do not assume Vercel history will always have it.
Failure Pattern — Rollback that looked like it worked but didn't
✕ Before (broken pattern)
✓ After (production pattern)
Lesson:
Rollback is operational when:
vercel rollback CLI command and can execute it without looking it upgit revert on a test commit and confirmed it creates a new commit rather than rewriting historygit reset --hard is wrong for a shared production branch and git revert is right