# How to Deploy a MERN Stack App on Heroku (2026 Guide)

> Step-by-step guide to deploying a MERN stack app on Heroku in 2026. Covers MongoDB Atlas, Express setup, React build, CORS, Procfile, and a faster alternative.
- **Author**: rohan-kulkarni
- **Published**: 2026-05-08
- **Modified**: 2026-05-08
- **Category**: Deployment Guides
- **URL**: https://kuberns.com/blogs/how-to-deploy-mern-app-on-heroku/

---

You can deploy a MERN stack app on Heroku, but it takes more steps than most tutorials show. You need a MongoDB Atlas database wired externally, an Express server configured to serve your React build as static files, CORS set to your production URL, a Procfile, and environment variables set manually through the Heroku dashboard.

This guide covers every step that actually works in 2026 and the real failure points that cause most MERN deployments to break on the first attempt.

**TL;DR**

- Heroku does not host MongoDB. You need a separate MongoDB Atlas cluster.
- React and Express must run as a single Heroku service with static file serving configured in Express.
- CORS must be explicitly set to your production Heroku URL, not localhost.
- Environment variables go in Heroku Config Vars, not in your local `.env` file.
- Total setup time: 45 to 90 minutes if everything goes right the first time.

> **Already know Heroku is painful and want to skip straight to the easy path?** See exactly how developers are deploying full MERN stacks in under 5 minutes without touching a Procfile. [The fastest way to deploy a MERN app in 2026.](https://kuberns.com/blogs/deploy-mern-app/)

## What You Need Before You Start

Make sure you have all of these before running a single command:

- **Node.js and npm** installed locally (v18 or higher recommended)
- **Git** installed and your project under version control
- **Heroku CLI** installed - download from `devcenter.heroku.com/articles/heroku-cli`
- **Heroku account** with a paid plan. Heroku removed the free tier - minimum is the Basic dyno at $7/month
- **MongoDB Atlas account** - free tier available at `cloud.mongodb.com`
- A working MERN app locally with a monorepo structure (frontend in `/client`, backend in root or `/server`)

> **Not sure which Heroku plan makes sense for your app?** A full breakdown of what each tier actually costs and what you get. [Heroku pricing explained with real numbers for 2026.](https://kuberns.com/blogs/heroku-pricing-explained/)

## How to Deploy a MERN App on Heroku: Step by Step

![Step by step guide to deploy MERN app on Heroku](https://kuberns-blogs-media.s3.ap-south-1.amazonaws.com/step-by-step-deploy-mern-on-heroku.png)

### Step 1: Set Up MongoDB Atlas for Production

Heroku has no native MongoDB support. Your database lives in MongoDB Atlas and connects to Heroku via a connection string.

**Create your Atlas cluster:**

1. Go to `cloud.mongodb.com` and sign up for a free account
2. Create a new project and click "Build a Cluster"
3. Select the free M0 tier (512MB storage, shared cluster)
4. Choose a region close to your Heroku app region
5. Click "Create Cluster" and wait 1 to 3 minutes

**Whitelist all IPs:**

Go to Network Access in the left sidebar and click "Add IP Address". Enter `0.0.0.0/0` and confirm.

Heroku uses dynamic IPs that change on every dyno restart. You cannot whitelist a specific IP for a Heroku app. If you whitelist only your local IP, your app will connect locally but fail silently in production.

**Get your connection string:**

Go to "Connect" on your cluster, choose "Connect your application", and copy the connection string. It looks like this:

```
mongodb+srv://<username>:<password>@cluster0.abc123.mongodb.net/<dbname>?retryWrites=true&w=majority
```

Replace `<username>`, `<password>`, and `<dbname>` with your actual values. Save this string. You will paste it as a Heroku Config Var in Step 5.

> **Using other databases with Heroku?** Here is every database option that actually works on Heroku in 2026, including what MongoDB Atlas replaces and what to use if you need PostgreSQL or Redis. [Heroku database options compared.](https://kuberns.com/blogs/heroku-database-options/)

### Step 2: Configure Express to Serve Your React Build

Both your React frontend and Express backend need to run as a single Heroku service. Express must be configured to build and serve the React app as static files.

**Install the path module (already in Node core, no install needed):**

In your `server.js` or `app.js`, add these lines after all your API routes:

```js
const path = require('path');

// Serve React production build
app.use(express.static(path.join(__dirname, 'client', 'build')));

// Catch-all: return React app for any unmatched route
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'client', 'build', 'index.html'));
});
```

The `app.get('*')` catch-all is critical. Without it, any direct URL visit to `/dashboard` or `/users/profile` returns a 404 from Express because Express does not know about React Router paths. The catch-all returns `index.html` for every unmatched route and lets React Router handle navigation on the client side.

Place the catch-all after all your API routes, not before them.

### Step 3: Handle CORS for Production

CORS that works on localhost breaks in production because the origin changes from `http://localhost:3000` to your Heroku app URL.

**Install the cors package if you have not already:**

```bash
npm install cors
```

**Configure cors() with your production origin:**

```js
const cors = require('cors');

const allowedOrigins = [
  'http://localhost:3000',
  'https://your-app-name.herokuapp.com'
];

app.use(cors({
  origin: function (origin, callback) {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  credentials: true
}));
```

Replace `your-app-name` with your actual Heroku app name. Add this block near the top of `server.js`, before any route definitions.

Leaving `origin: '*'` causes problems with authenticated requests. Setting it explicitly to your production URL is the correct approach.

### Step 4: Configure package.json and Procfile

Two files control how Heroku builds and starts your MERN app.

**Root package.json - add engines and heroku-postbuild:**

```json
{
  "name": "your-mern-app",
  "version": "1.0.0",
  "engines": {
    "node": "18.x"
  },
  "scripts": {
    "start": "node server.js",
    "heroku-postbuild": "cd client && npm install && npm run build"
  }
}
```

The `engines` field tells Heroku which Node version to use. Without it, Heroku picks a default that may not match your local version, which causes silent build failures. The `heroku-postbuild` script runs automatically after Heroku installs root dependencies. It goes into the client directory, installs React dependencies, and builds the production bundle that Express then serves as static files.

**Create a Procfile in the root of your project:**

```
web: node server.js
```

No file extension on the Procfile. One line. This tells Heroku to start your app by running `node server.js` on the web dyno.

### Step 5: Push and Deploy to Heroku

With Atlas connected, Express configured, CORS set, and your Procfile in place, you are ready to deploy.

**Login and create your Heroku app:**

```bash
heroku login
heroku create your-app-name
```

**Set Config Vars in the Heroku dashboard:**

Go to your app in the Heroku dashboard, open Settings, and click "Reveal Config Vars". Add:

| Key | Value |
|---|---|
| `MONGODB_URI` | Your full MongoDB Atlas connection string |
| `NODE_ENV` | `production` |
| `PORT` | Leave blank - Heroku sets this automatically |

Do not commit your `.env` file to Git. Config Vars are the production equivalent of your local `.env`.

**Push to Heroku:**

```bash
git add .
git commit -m "configure for heroku deployment"
git push heroku main
```

**Watch the build logs:**

```bash
heroku logs --tail
```

This streams live logs. The build runs `heroku-postbuild`, installs dependencies, compiles the React app, then starts the Node server. If anything fails, the error will appear here.

**Open your app:**

```bash
heroku open
```

> **Want to trigger deployments automatically on every GitHub push instead of running git push heroku main manually?** Here is how to set up GitHub integration with Heroku so deploys happen on merge. [Heroku GitHub integration setup guide.](https://kuberns.com/blogs/heroku-github-integration/)

## Common Errors You Will Hit Deploying MERN on Heroku

![Common MERN Heroku deployment errors](https://kuberns-blogs-media.s3.ap-south-1.amazonaws.com/common-heroku-mern-errors.png)

These are the exact errors developers encounter after following the steps above. Each one is fixable, but each one costs real debugging time.

| Error | Cause | Avg Debug Time |
|---|---|---|
| `MongoServerSelectionError` | Atlas IP not whitelisted with `0.0.0.0/0` | 30 to 60 min |
| Blank white screen on frontend | React build not served as static files by Express | 45 to 90 min |
| CORS error in browser console | `origin` in `cors()` still set to localhost | 30 to 60 min |
| `H10 App Crashed` on startup | Missing `start` script or wrong Procfile content | 30 to 45 min |
| `Cannot find module` on deploy | `heroku-postbuild` not running client build | 20 to 40 min |
| React Router 404 on every refresh | Missing `app.get('*')` catch-all route in Express | 20 to 30 min |
| Slug size too large, push rejected | `node_modules` not listed in `.slugignore` | 15 to 30 min |

Every one of these errors is fixable. But for a team trying to ship a product, this is the real cost of choosing Heroku for a MERN stack. The deployment is not the product. The time spent debugging it is time taken away from building features.

> **Reconsidering Heroku after seeing this list?** Every platform that replaces Heroku in 2026, with honest pricing and deployment speed comparisons. [The complete guide to Heroku alternatives.](https://kuberns.com/blogs/the-ultimate-guide-to-heroku-alternatives-in-2025/)

## How Long This Actually Takes vs. What You Expected

Most tutorials say deploying a MERN app on Heroku takes "about 30 minutes". Here is what it actually takes:

| Task | Optimistic | Realistic |
|---|---|---|
| MongoDB Atlas setup and IP whitelist | 10 min | 15 to 25 min |
| Express static file + catch-all config | 10 min | 20 to 40 min |
| CORS debugging | 5 min | 30 to 60 min |
| Procfile and package.json setup | 5 min | 15 to 20 min |
| First push and watching logs | 5 min | 20 to 45 min |
| **Total** | **35 min** | **100 to 190 min** |

The gap between optimistic and realistic comes from the errors in the table above. Most first-time MERN-on-Heroku deploys hit at least two of them.

On top of the setup time, the ongoing cost adds up. A single Basic Heroku dyno starts at $7/month. Once your app exceeds Atlas free tier limits (512MB storage, 100 shared connections), you pay for Atlas too. A production-ready setup runs $20 to $50/month before you add any monitoring or logging add-ons.

> **Looking at what this costs long term before you commit?** The full breakdown of Heroku's dyno pricing, add-on costs, and where the real charges appear on your bill. [Heroku pricing explained in full.](https://kuberns.com/blogs/heroku-pricing-explained/)

## Deploy Your MERN Stack with Agentic AI on Kuberns

![Deploy MERN stack with agentic AI on Kuberns](https://kuberns-blogs-media.s3.ap-south-1.amazonaws.com/kuberns-home-page-new.png)

Everything in this guide is what Heroku requires from you. It is not optional. Every step has a failure mode. Kuberns takes a different approach entirely.

Kuberns is an agentic AI cloud platform built on AWS. When you connect your MERN repository, the AI reads your code, detects that it is a MERN project, identifies your folder structure and runtime, and provisions your entire production stack automatically. No Procfile. No buildpack configuration. No MongoDB Atlas account setup. No manual CORS changes.

Here is what the AI handles without you writing a single config file:

- AWS server provisioned and sized to your app automatically
- MongoDB-compatible database created and connected
- Database connection string injected as an environment variable
- CORS configured internally based on your stack
- React frontend built and wired to Express as a unified service
- SSL certificate issued and attached
- CI/CD activated on every push to your main branch
- Auto-scaling based on real traffic

<a href="https://dashboard.kuberns.com" target="_blank" rel="noopener noreferrer">
  <img src="https://kuberns-blogs-media.s3.ap-south-1.amazonaws.com/deploy-on-kuberns-bannner6.png" alt="Deploy MERN on Kuberns" style={{ width: '100%', height: 'auto', cursor: 'pointer' }} />
</a>

Here is how Kuberns compares to the Heroku setup you just read through:

| Task | Heroku | Kuberns Agentic AI |
|---|---|---|
| MongoDB setup | Manual Atlas account + IP whitelist + connection string | Automatic |
| CORS configuration | Manual code change + redeploy to test | Handled automatically |
| React build wiring | `heroku-postbuild` script + `express.static` config | Detected and handled |
| Procfile | Required | Not needed |
| Environment variables | Set manually in dashboard | Injected automatically |
| Time to first deploy | 45 to 90 minutes | Under 5 minutes |
| Debug surface area | 6 or more common failure points | Near zero |
| Monthly cost vs raw AWS | Baseline Heroku pricing | Up to 40% less |

**Deploy your MERN app on Kuberns in 3 steps:**
1. Connect your GitHub repo to Kuberns
2. Set your environment variables in the dashboard
3. Click Deploy and get a live HTTPS URL in under 5 minutes

[Start free with $14 in credits, no credit card needed.](https://dashboard.kuberns.com/)

> **Want to see the full Kuberns MERN deployment walkthrough with screenshots?** Step-by-step guide to deploying a MERN app with agentic AI, zero config files, and automatic MongoDB provisioning. [The fastest way to deploy a MERN app in 2026.](https://kuberns.com/blogs/deploy-mern-app/)

## Conclusion

Deploying a MERN stack on Heroku works, but it requires getting six separate things right: MongoDB Atlas setup, Express static file serving, CORS configuration, Procfile, `package.json` scripts, and environment variables. Any one of them can fail silently and take 30 to 90 minutes to debug.

If you are building a product and want your deployment to be the easy part, Kuberns handles the entire MERN stack automatically. No configuration files. No Atlas account setup. No CORS debugging. Just connect your repo and deploy.

[Try Kuberns free](https://dashboard.kuberns.com/) and get your MERN app live in under 5 minutes.

<a href="https://dashboard.kuberns.com" target="_blank" rel="noopener noreferrer">
  <img src="https://kuberns-blogs-media.s3.ap-south-1.amazonaws.com/CTA_banner.png" alt="Deploy on Kuberns" style={{ width: '100%', height: 'auto', cursor: 'pointer' }} />
</a>

## FAQ

### Q: Does Heroku support MongoDB natively?

No. Heroku removed the mLab MongoDB add-on and does not provide MongoDB as a native service. You need a separate MongoDB Atlas cluster and connect it to Heroku via a connection string in Config Vars.

### Q: How do I connect MongoDB Atlas to a Heroku app?

Create a free Atlas cluster, set Network Access to allow all IPs (`0.0.0.0/0`), copy the connection string, and add it as `MONGODB_URI` in your Heroku app's Config Vars under Settings. Use `process.env.MONGODB_URI` in your Node.js code to read it.

### Q: Why is my React app showing a blank screen on Heroku?

Express is not serving the React build as static files. Add `app.use(express.static(path.join(__dirname, 'client/build')))` and a catch-all `app.get('*')` that returns `index.html`. Without these, Heroku serves nothing for the frontend routes.

### Q: How do I fix CORS errors when deploying MERN on Heroku?

Set the `origin` in your `cors()` middleware to your exact Heroku production URL. Do not use `origin: '*'` for authenticated requests. The origin must match the domain your React app is served from in production.

### Q: What is a Procfile and do I need one for MERN on Heroku?

A Procfile is a plain text file in your repo root that tells Heroku how to start your app. For MERN, it should contain one line: `web: node server.js`. Without it, Heroku may not start your server or may use the wrong entry point.

### Q: How much does it cost to deploy a MERN app on Heroku in 2026?

The Basic dyno costs $7/month. MongoDB Atlas has a free M0 tier but production apps that exceed 512MB storage or 100 connections need a paid Atlas plan starting at $9/month. A realistic production MERN setup on Heroku costs $20 to $50/month.

### Q: Can I deploy frontend and backend together on Heroku?

Yes. Configure Express to serve the React production build as static files and use a `heroku-postbuild` script to compile the React app during deployment. Both run as one Heroku dyno on a single URL.

### Q: What is the fastest way to deploy a MERN stack app?

Kuberns. Connect your GitHub repo, set environment variables, and click Deploy. The agentic AI detects your MERN stack, provisions a MongoDB-compatible database, configures CORS, builds your React frontend, and gives you a live HTTPS URL in under 5 minutes with no Procfile or buildpack configuration.

---
- [More Deployment Guides articles](https://kuberns.com/blogs/category/deployment-guides/1/)
- [All articles](https://kuberns.com/blogs/)