Skip to content

Mean 18 Deployment

DodaTech 5 min read

title: "MEAN Stack Deployment — Heroku and Railway Options" description: "Deploy a MEAN Stack application to Heroku or Railway with Express backend, Angular frontend, MongoDB Atlas, environment configuration, and CI/CD." weight: 28 date: 2026-06-28 lastmod: 2026-06-28 tags: [frameworks, mean]

Deploying a MEAN stack application requires hosting the Express backend, the Angular frontend, and connecting to a production MongoDB database.

What You'll Learn

You will deploy a MEAN application to Railway (recommended) or Heroku, configure environment variables, build scripts, and set up automatic deployments.

Why It Matters

Deployment makes your application accessible to users. Proper configuration prevents downtime and ensures smooth updates.

Real-World Use

DodaTech deploys MEAN applications on Railway with automatic deployments from GitHub, environment-specific configuration, and MongoDB Atlas for the database.

flowchart LR
    A[Git Push] --> B[GitHub Repository]
    B --> C[Railway/Heroku]
    C --> D[Build Angular]
    C --> E[Start Express]
    C --> F[Connect MongoDB Atlas]
    D --> G[Serve Frontend]
    E --> H[Serve API]
    style C fill:#4a90d9,color:#fff

Preparing the Express Backend

Configure the backend for production deployment.

// backend/server.js — production ready
const express = require('express');
const path = require('path');
const cors = require('cors');
require('dotenv').config();

const app = express();

// Middleware
app.use(cors());
app.use(express.json());

// Serve Angular static files in production
if (process.env.NODE_ENV === 'production') {
  app.use(express.static(path.join(__dirname, '../frontend/dist/mean-frontend')));
}

// API routes
app.use('/api/auth', authRoutes);
app.use('/api/users', userRoutes);
app.use('/api/products', productRoutes);

// Serve Angular index.html for all non-API routes
if (process.env.NODE_ENV === 'production') {
  app.get('*', (req, res) => {
    res.sendFile(path.join(__dirname, '../frontend/dist/mean-frontend/index.html'));
  });
}

// Error handler
app.use(errorHandler);

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Expected output: In production, Express serves the built Angular files. API routes are prefixed with /api. All other routes return the Angular index.html for SPA routing.

Package.json Configuration

Configure the root package.json for deployment.

{
  "name": "mean-stack-app",
  "version": "1.0.0",
  "scripts": {
    "install": "cd backend && npm install && cd ../frontend && npm install",
    "build": "cd frontend && npm run build -- --configuration production",
    "start": "cd backend && node server.js",
    "dev": "cd backend && npm run dev"
  },
  "engines": {
    "node": "18.x"
  }
}

Expected output: The install script installs dependencies for both backend and frontend. The build script compiles the Angular app for production.

Building the Angular Frontend

Build the Angular app for production.

cd frontend
npm run build -- --configuration production

Expected output: A production build in frontend/dist/mean-frontend/. The build is optimized with minification, tree-shaking, and AOT compilation.

Environment Variables

Set production environment variables.

# Production environment
NODE_ENV=production
PORT=3000
MONGODB_URI=mongodb+srv://<user>:<password>@cluster.mongodb.net/mean-app
JWT_SECRET=your-production-secret-key

Expected output: Environment variables configured in the deployment platform. MONGODB_URI points to the production Atlas cluster. JWT_SECRET is a strong random string.

Deploying to Railway

Railway simplifies deployment with automatic builds and HTTPS.

# Install Railway CLI
npm install -g @railway/cli

# Login and deploy
railway login
railway init
railway up
// railway.json — optional Railway configuration
{
  "build": {
    "builder": "NIXPACKS",
    "buildCommand": "npm run build"
  },
  "deploy": {
    "startCommand": "npm start",
    "healthcheckPath": "/api/health"
  }
}

Expected output: Railway detects the Node.js project, installs dependencies, builds the Angular frontend, starts the Express server, and provides a public URL with HTTPS.

Deploying to Heroku

Heroku deployment with Git-based workflow.

# Install Heroku CLI
npm install -g heroku

# Login and create app
heroku login
heroku create my-mean-app

# Set buildpack
heroku buildpacks:set heroku/nodejs

# Set environment variables
heroku config:set NODE_ENV=production
heroku config:set MONGODB_URI=mongodb+srv://...
heroku config:set JWT_SECRET=your-secret

# Deploy
git push heroku main
// Procfile — Heroku process type
web: npm start

Expected output: Heroku builds and deploys the application. The Procfile tells Heroku how to start the server. Environment variables are set via CLI.

Common Mistakes

  1. Not configuring the Angular API URL for production: The Angular environment.prod.ts should use a relative API URL (/api) that works on the same domain.

  2. Forgetting to serve Angular static files: The Express server must serve the built Angular files. Without this, the frontend does not load.

  3. Not setting up the wildcard route for SPA: Angular uses client-side routing. The Express server must return index.html for all non-API routes.

  4. Hardcoding environment variables in code: Use process.env for all environment-specific values. Never hardcode secrets.

  5. Not enabling HTTPS: Both Railway and Heroku provide HTTPS. Use it. Do not run production APIs over HTTP.

Practice Questions

  1. How does Express serve the Angular frontend in production?

Express uses express.static() to serve the built Angular files from the dist directory. A wildcard route returns index.html for SPA routing.

  1. What is the purpose of the build script in package.json?

It compiles the Angular frontend for production with AOT compilation, minification, and tree-shaking.

  1. How do you set environment variables on Railway?

Through the Railway dashboard or CLI: railway variables set KEY=VALUE.

  1. How do you handle SPA routing on the server?

Express returns index.html for all non-API routes. Angular handles client-side routing from there.

  1. What is the Procfile for Heroku?

It declares the process type and start command. For Node.js: web: npm start.

Challenge

Deploy a complete MEAN application to Railway with: MongoDB Atlas connection, production Angular build, Express serving static files, SPA routing, environment variables, and automatic deployments from GitHub.

Frequently Asked Questions

Should I deploy backend and frontend separately?

Separate deployment allows independent scaling. Combined deployment is simpler. Start with combined and split if needed.

How do I handle CORS in production?

When Express serves Angular from the same domain in production, CORS is not needed. Configure CORS to allow the production domain.

What is the best hosting for MEAN apps?

Railway, Heroku, DigitalOcean App Platform, and AWS Elastic Beanstalk all support Node.js deployments. Railway offers the simplest setup.

{{< faq "How do I monitor the production app?" >> Use Railway or Heroku dashboards for logs and metrics. Add application monitoring with Sentry or New Relic. {{< /faq >}}

How do I run database migrations in production?

Create a migration script that runs before the server starts. Use a separate command or run it in the build phase.

Mini Project

Prepare a MEAN application for production by: configuring environment files, updating the Express server to serve static files, setting up SPA routing, creating deployment scripts, and deploying to Railway or Heroku.

What's Next

Learn Testing strategies for the MEAN stack application.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro