Why Vite's Proxy Only Works in Dev And What to Do About It

Why Vite's Proxy Only Works in Dev And What to Do About It

If you've ever built a frontend using Vite and tried to connect it to an API server, you've probably made use of the server.proxy option in your vite.config.js. During local development, it works like magic. You write something like:

// vite.config.js
export default defineConfig({
  server: {
    proxy: {
      '/api': 'http://localhost:3000',
    }
  }
});

...and just like that, your frontend requests to /api are proxied to your backend.

Related: Setting Up a Dev Server Proxy in Vite

But then you deploy to Vercel, Netlify, or another static hosting provider. Suddenly your perfectly working requests start failing with 404 errors or CORS issues.

So what gives?

The Key Thing to Know

Vite's server.proxy is strictly a development-time feature.

It's part of the dev server that Vite spins up to make development easier. When you run vite or npm run dev, Vite handles proxying API requests to your backend for convenience.

But once you run vite build, Vite generates static assets (HTML, CSS, JS) and discards anything related to server-side behavior. There is no dev server in production, so proxy rules simply don't exist anymore.

Why It Matters

If you're relying on /api to work in production, you need to ensure your hosting provider knows how to handle that route. Otherwise, your requests will go nowhere.

This is especially tricky when deploying to:

  • Vercel (which serves static files unless you configure rewrites)
  • Netlify (which also needs rewrite rules for API routes)
  • Cloudflare Pages, S3, etc.

If you’re deploying your backend separately (e.g., on Render, Railway, or a VPS), and your frontend is on Vercel, the frontend will have no idea what /api means without extra configuration.

What You Can Do About It

Option 1: Use Absolute URLs in Production

Instead of relying on /api, just use the full API endpoint.

const baseURL = import.meta.env.PROD
  ? 'https://api.mysite.com'
  : '/api';

fetch(`${baseURL}/user`) // works locally and in production

Set the production base URL in your .env.production file:

VITE_API_BASE_URL=https://api.mysite.com

Option 2: Set Up Rewrites on Your Host

Vercel Example (vercel.json):

{
  "rewrites": [
    { "source": "/api/(.*)", "destination": "https://api.mysite.com/api/$1" }
  ]
}

This tells Vercel to forward all /api requests to your backend.

Netlify Example (_redirects file):

/api/*  https://api.mysite.com/api/:splat  200

Option 3: Host Frontend and Backend Together

If you're deploying a fullstack app (e.g., Express + Vite), you can serve the Vite-built files directly from your backend server. Then /api and your frontend live on the same domain, no proxying or CORS needed.

This avoids cross-origin issues entirely:

// server.js
app.use(express.static(path.join(__dirname, 'dist')));
app.use('/api', apiRouter);

Final Advice

Don't let Vite's magical dev proxy fool you. It's a convenience feature, not a production tool. Always:

  • Know your production environment
  • Plan how frontend talks to backend
  • Use absolute URLs or configure host rewrites

Once you understand that, Vite stops being mysterious and starts being powerful.

TL;DR

  • server.proxy only works in development.
  • In production, Vite serves static files only.
  • Use absolute URLs, rewrites, or host your backend together with the frontend.

If you spent hours debugging a broken API connection after deploying, you're not alone. But now you know better.

Walter Guevara is a Computer Scientist, software engineer, startup founder and previous mentor for a coding bootcamp. He has been creating software for the past 20 years.

Community Comments

No comments posted yet

Code Your Own Classic Snake Game – The Right Way

Master the fundamentals of game development and JavaScript with a step-by-step guide that skips the fluff and gets straight to the real code.

Ad Unit

Current Poll

Help us and the community figure out what the latest trends in coding are.

Total Votes:
Q:
Submit

Add a comment