Vercel Deploy Stuck on "Building"

Build never finishes — typically OOM, dependency deadlock, or build timeout.

A Vercel deployment shows Building and just sits there — 15 minutes, no new log lines, no error. “Stuck building” is a different failure mode from “build failed.” Failed throws an explicit error and exits; stuck means the process is alive but making no progress. Vercel’s default build timeout is 45 minutes (Hobby) or 60 minutes (Pro) before it’s force-killed. Before that, what you’re seeing is usually a deadlocked npm install, static generation hanging on one page, a postbuild hook calling an API that never returns, or a single worker SSG-ing thousands of pages serially. This guide gives a hit-rate-ordered diagnosis with concrete timeout config.

Common causes

Ordered by hit rate, highest first.

1. Static generation stuck on one page

getStaticProps / Astro’s getStaticPaths calls an external API without a timeout, the upstream hangs. Next.js / Astro process pages serially by default — one stalls, everything after it waits. The log’s last line is usually Generating static pages (XX/YY) and then nothing.

Linting and checking validity of types ...
Collecting page data ...
Generating static pages (847/3214) ...
[stuck here for 30 minutes]

How to spot it: Generating static pages (X/Y) doesn’t increment for > 5 minutes → almost certain.

2. npm install network deadlock

npm install tries to pull a package whose registry is unreachable (private registry, blocked CDN, 404 git URL) and retries until the build timeout. Log stops at Installing dependencies... with nothing after.

npm warn deprecated ...
[no new lines for many minutes]

How to spot it: last log segment is install-phase; you never see Build completed in installation step or the framework name appear.

3. Build OOM — memory pegged but no crash

Not the instant exited with 137. Instead, heap pressure hits 99% and GC runs constantly; the process doesn’t die but each step slows to near-zero. Common in large TS projects with heavy type inference, webpack chunk splitting, or Turborepo parallel tasks.

How to spot it: gaps between log timestamps get longer (hundreds of lines in the first 5 minutes, then 1-2 per minute) — that’s GC thrashing.

4. Postbuild hook calling external service hangs

package.json has "postbuild": "node scripts/notify-cdn.js"; the script fetches a webhook without a timeout, or sitemap-generator crawls the site and stalls on a slow URL.

$ next build && next-sitemap
✓ Generating static pages (1000/1000)
$ next-sitemap
[stuck here]

How to spot it: log shows the main build finished ( or Build completed) but status is still Building — postbuild step is the culprit.

5. Corrupted build cache

Vercel reuses the previous build’s .next/cache or node_modules by default. If something corrupt is in there, the build can read it repeatedly and hang or error.

How to spot it: same commit builds fine locally, hangs on Vercel; the deployment’s build cache timestamp is unusually old.

6. Edge case: --watch mode in the build command

vercel.json or build command was set to next dev / vite --watch by mistake. The process never exits, building shows forever.

How to spot it: log contains ready - started server on ... or watching for changes — wrong build command.

Shortest path to fix

Step 1: Cancel manually and read where the log stopped

Dashboard → the building deployment → top-right ...Cancel Build. After cancellation the last 50-100 lines of output remain — gold for diagnosis.

Copy the tail:

vercel logs <deployment-url> > stuck.log
tail -50 stuck.log

Match against the “Common causes” above to identify the phase.

Step 2: Stuck in static generation — add timeouts to external calls

If the log stalled at Generating static pages (X/Y), grep every untimed external call in getStaticProps / getStaticPaths / fetch(:

// Bad: no timeout
const data = await fetch(`https://api.example.com/posts/${id}`).then(r => r.json());

// Fixed: 8-second timeout with fallback
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 8000);
try {
  const data = await fetch(url, { signal: controller.signal }).then(r => r.json());
  return { props: { data } };
} catch (e) {
  console.warn(`Skipping ${id}: ${e.message}`);
  return { props: { data: null } };  // don't block the build
} finally {
  clearTimeout(timeout);
}

Step 3: Thousands of pages — switch to ISR / On-Demand

Don’t pre-generate thousands of static pages at build time. Next.js:

// pages/[slug].tsx
export async function getStaticPaths() {
  return {
    paths: [],            // pre-build nothing
    fallback: 'blocking', // generate on first request, then cache
  };
}

export async function getStaticProps({ params }) {
  return {
    props: { ... },
    revalidate: 3600,     // background revalidate every hour
  };
}

Astro: use output: 'hybrid' + prerender = false on dynamic routes.

Step 4: Raise build memory + watch GC

# package.json
{
  "scripts": {
    "build": "NODE_OPTIONS='--max-old-space-size=8192 --trace-gc' next build"
  }
}

--trace-gc prints every GC pause to stdout — you can see directly whether GC thrashing is the bottleneck. Hobby caps at 8GB; beyond that, you need Pro.

Step 5: Clear build cache and redeploy

Dashboard → next to the deployment, ...Redeploy, then uncheck Use existing Build Cache. Forces a fresh install + build.

Or via CLI:

vercel --force

If clearing the cache fixes it, the cache was corrupt. Bust it more often by adding a version field to package.json (changes the cache key).

Prevention

  • Force every fetch in getStaticProps / getStaticPaths to use AbortSignal.timeout(8000)
  • Beyond ~200 pages, switch to ISR / on-demand — don’t bulk-generate at build time
  • Add a build-duration alert in CI: fail when duration exceeds 1.5x the rolling average, forcing optimization
  • Every postbuild script should have a timeout + explicit process.exit(0)
  • Track deployment duration trends; a slow upward creep is usually early tech debt
  • Manually clear the build cache periodically (monthly), to avoid corrupt files accumulating

Tags: #Hosting #Debug #Troubleshooting #Vercel #Build error