The Only Cheatsheets

Comprehensive collection of your cheatsheets

View project on GitHub

Complete Backend Development Cheatsheet

From Beginner to Advanced

Download PDF

Table of Contents

  1. Backend Fundamentals
  2. JavaScript Essentials
  3. Node.js
  4. Express.js
  5. Next.js API Routes
  6. Database Management
  7. API Development
  8. Authentication & Security
  9. Testing
  10. Deployment & DevOps
  11. Advanced Concepts

Backend Fundamentals

What is Backend Development?

Backend development involves server-side programming, database management, API creation, and server configuration. The backend handles business logic, data storage, authentication, and serves data to frontend applications.

Key Backend Concepts

  • Server: Computer that provides services to other computers
  • API: Application Programming Interface for communication
  • Database: Storage system for application data
  • HTTP/HTTPS: Protocol for web communication
  • REST: Architectural style for web services
  • CRUD: Create, Read, Update, Delete operations

HTTP Methods

GET     - Retrieve data
POST    - Create new data
PUT     - Update entire resource
PATCH   - Partial update
DELETE  - Remove data
HEAD    - Headers only
OPTIONS - Allowed methods

HTTP Status Codes

2xx Success
200 OK
201 Created
204 No Content

3xx Redirection
301 Moved Permanently
302 Found
304 Not Modified

4xx Client Error
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
422 Unprocessable Entity

5xx Server Error
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable

JavaScript Essentials

ES6+ Features for Backend

// Arrow Functions
const getData = async () => {
  return await fetchData();
};

// Destructuring
const { name, email } = user;
const [first, second] = array;

// Template Literals
const message = `Hello ${name}, welcome!`;

// Spread Operator
const newArray = [...oldArray, newItem];
const newObject = { ...oldObject, newProperty: value };

// Promises and Async/Await
const fetchData = async () => {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
};

// Classes
class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }
  
  async save() {
    // Save to database
  }
}

// Modules
// Export
export const helper = () => {};
export default MyClass;

// Import
import MyClass, { helper } from './module.js';

Error Handling

// Try-Catch
try {
  const result = riskyOperation();
} catch (error) {
  console.error('Error occurred:', error.message);
} finally {
  // Cleanup code
}

// Custom Error Classes
class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = 'ValidationError';
  }
}

// Error Middleware (Express)
const errorHandler = (err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Something went wrong!' });
};

Node.js

Core Concepts

Node.js is a JavaScript runtime built on Chrome’s V8 engine, allowing JavaScript to run on servers.

NPM (Node Package Manager)

# Initialize project
npm init -y

# Install packages
npm install express mongoose
npm install -D nodemon jest

# Scripts in package.json
{
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js",
    "test": "jest"
  }
}

Core Modules

// File System
const fs = require('fs');
const fsPromises = require('fs').promises;

// Read file
fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});

// Write file
fs.writeFile('output.txt', 'Hello World', (err) => {
  if (err) throw err;
  console.log('File saved!');
});

// Path
const path = require('path');
const fullPath = path.join(__dirname, 'files', 'data.txt');
const extension = path.extname('file.txt');

// HTTP
const http = require('http');
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World');
});

// URL
const url = require('url');
const parsedUrl = url.parse(req.url, true);

// Crypto
const crypto = require('crypto');
const hash = crypto.createHash('sha256').update('password').digest('hex');

// Events
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => console.log('Event fired!'));

Environment Variables

// Using dotenv
require('dotenv').config();

const PORT = process.env.PORT || 3000;
const DB_URL = process.env.DATABASE_URL;

// .env file
PORT=3000
DATABASE_URL=mongodb://localhost:27017/myapp
JWT_SECRET=your-secret-key

Process Management

// Process events
process.on('uncaughtException', (err) => {
  console.error('Uncaught Exception:', err);
  process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});

// Graceful shutdown
process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down gracefully');
  server.close(() => {
    process.exit(0);
  });
});

Express.js

Basic Setup

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'));

// Routes
app.get('/', (req, res) => {
  res.json({ message: 'Hello World!' });
});

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

Routing

// Basic routes
app.get('/users', getAllUsers);
app.get('/users/:id', getUserById);
app.post('/users', createUser);
app.put('/users/:id', updateUser);
app.patch('/users/:id', partialUpdateUser);
app.delete('/users/:id', deleteUser);

// Route parameters
app.get('/users/:id/posts/:postId', (req, res) => {
  const { id, postId } = req.params;
  res.json({ userId: id, postId });
});

// Query parameters
app.get('/search', (req, res) => {
  const { q, page, limit } = req.query;
  res.json({ query: q, page, limit });
});

// Express Router
const router = express.Router();

router.get('/', (req, res) => {
  res.json({ message: 'Users route' });
});

router.post('/', (req, res) => {
  // Create user logic
});

app.use('/api/users', router);

Middleware

// Custom middleware
const logger = (req, res, next) => {
  console.log(`${req.method} ${req.path} - ${new Date().toISOString()}`);
  next();
};

// Authentication middleware
const authenticate = (req, res, next) => {
  const token = req.header('Authorization')?.replace('Bearer ', '');
  
  if (!token) {
    return res.status(401).json({ error: 'Access denied' });
  }
  
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (error) {
    res.status(400).json({ error: 'Invalid token' });
  }
};

// Validation middleware
const validateUser = (req, res, next) => {
  const { name, email } = req.body;
  
  if (!name || !email) {
    return res.status(400).json({ error: 'Name and email required' });
  }
  
  next();
};

// Error handling middleware
const errorHandler = (err, req, res, next) => {
  console.error(err.stack);
  
  if (err.name === 'ValidationError') {
    return res.status(400).json({ error: err.message });
  }
  
  res.status(500).json({ error: 'Internal server error' });
};

// Apply middleware
app.use(logger);
app.use('/api/protected', authenticate);
app.use(errorHandler);

Request and Response

// Request object
app.post('/api/users', (req, res) => {
  console.log('Body:', req.body);
  console.log('Params:', req.params);
  console.log('Query:', req.query);
  console.log('Headers:', req.headers);
  console.log('Cookies:', req.cookies);
  console.log('Method:', req.method);
  console.log('URL:', req.url);
  console.log('IP:', req.ip);
});

// Response methods
app.get('/api/users', (req, res) => {
  // Send JSON
  res.json({ users: [] });
  
  // Send status with data
  res.status(201).json({ message: 'Created' });
  
  // Send file
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
  
  // Set headers
  res.set('Custom-Header', 'value');
  
  // Redirect
  res.redirect('/login');
  
  // Send cookies
  res.cookie('token', 'abc123', { httpOnly: true });
});

Next.js API Routes

API Routes Structure

pages/
  api/
    users/
      index.js      // /api/users
      [id].js       // /api/users/:id
      create.js     // /api/users/create
    auth/
      login.js      // /api/auth/login
      register.js   // /api/auth/register

Basic API Route

// pages/api/users/index.js
export default function handler(req, res) {
  if (req.method === 'GET') {
    // Get all users
    res.status(200).json({ users: [] });
  } else if (req.method === 'POST') {
    // Create user
    const { name, email } = req.body;
    res.status(201).json({ message: 'User created', user: { name, email } });
  } else {
    res.setHeader('Allow', ['GET', 'POST']);
    res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

Dynamic API Routes

// pages/api/users/[id].js
export default function handler(req, res) {
  const { id } = req.query;
  
  switch (req.method) {
    case 'GET':
      res.status(200).json({ user: { id, name: 'John' } });
      break;
    case 'PUT':
      const { name, email } = req.body;
      res.status(200).json({ message: `User ${id} updated` });
      break;
    case 'DELETE':
      res.status(200).json({ message: `User ${id} deleted` });
      break;
    default:
      res.setHeader('Allow', ['GET', 'PUT', 'DELETE']);
      res.status(405).end(`Method ${req.method} Not Allowed`);
  }
}

Middleware in Next.js

// middleware.js
import { NextResponse } from 'next/server';

export function middleware(request) {
  // Check authentication
  const token = request.cookies.get('token');
  
  if (!token && request.nextUrl.pathname.startsWith('/api/protected')) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }
  
  return NextResponse.next();
}

export const config = {
  matcher: '/api/protected/:path*'
};

App Router API Routes (Next.js 13+)

// app/api/users/route.js
import { NextRequest, NextResponse } from 'next/server';

export async function GET(request) {
  return NextResponse.json({ users: [] });
}

export async function POST(request) {
  const body = await request.json();
  return NextResponse.json({ message: 'User created' }, { status: 201 });
}

// app/api/users/[id]/route.js
export async function GET(request, { params }) {
  const { id } = params;
  return NextResponse.json({ user: { id } });
}

Database Management

MongoDB with Mongoose

Setup and Connection

const mongoose = require('mongoose');

// Connection
const connectDB = async () => {
  try {
    await mongoose.connect(process.env.MONGODB_URI, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    });
    console.log('MongoDB connected');
  } catch (error) {
    console.error('Database connection error:', error);
    process.exit(1);
  }
};

// Schema Definition
const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, 'Name is required'],
    trim: true,
    maxlength: 50
  },
  email: {
    type: String,
    required: true,
    unique: true,
    lowercase: true,
    match: [/^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/, 'Invalid email']
  },
  password: {
    type: String,
    required: true,
    minlength: 6
  },
  role: {
    type: String,
    enum: ['user', 'admin'],
    default: 'user'
  },
  createdAt: {
    type: Date,
    default: Date.now
  },
  profile: {
    age: Number,
    bio: String
  }
}, {
  timestamps: true
});

// Middleware
userSchema.pre('save', async function(next) {
  if (!this.isModified('password')) return next();
  this.password = await bcrypt.hash(this.password, 12);
  next();
});

// Methods
userSchema.methods.comparePassword = async function(candidatePassword) {
  return await bcrypt.compare(candidatePassword, this.password);
};

// Static methods
userSchema.statics.findByEmail = function(email) {
  return this.findOne({ email });
};

const User = mongoose.model('User', userSchema);

CRUD Operations

// Create
const createUser = async (userData) => {
  try {
    const user = new User(userData);
    await user.save();
    return user;
  } catch (error) {
    throw error;
  }
};

// Read
const getAllUsers = async () => {
  return await User.find().select('-password');
};

const getUserById = async (id) => {
  return await User.findById(id).select('-password');
};

// Update
const updateUser = async (id, updateData) => {
  return await User.findByIdAndUpdate(
    id, 
    updateData, 
    { new: true, runValidators: true }
  ).select('-password');
};

// Delete
const deleteUser = async (id) => {
  return await User.findByIdAndDelete(id);
};

// Complex queries
const searchUsers = async (query, page = 1, limit = 10) => {
  const skip = (page - 1) * limit;
  
  return await User.find({
    $or: [
      { name: { $regex: query, $options: 'i' } },
      { email: { $regex: query, $options: 'i' } }
    ]
  })
  .select('-password')
  .skip(skip)
  .limit(limit)
  .sort({ createdAt: -1 });
};

SQL with PostgreSQL (using pg)

const { Pool } = require('pg');

// Database connection
const pool = new Pool({
  user: process.env.DB_USER,
  host: process.env.DB_HOST,
  database: process.env.DB_NAME,
  password: process.env.DB_PASSWORD,
  port: process.env.DB_PORT,
});

// Create table
const createUsersTable = async () => {
  const query = `
    CREATE TABLE IF NOT EXISTS users (
      id SERIAL PRIMARY KEY,
      name VARCHAR(100) NOT NULL,
      email VARCHAR(100) UNIQUE NOT NULL,
      password VARCHAR(255) NOT NULL,
      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )
  `;
  
  try {
    await pool.query(query);
    console.log('Users table created');
  } catch (error) {
    console.error('Error creating table:', error);
  }
};

// CRUD Operations
const userQueries = {
  // Create
  createUser: async (name, email, hashedPassword) => {
    const query = 'INSERT INTO users (name, email, password) VALUES ($1, $2, $3) RETURNING id, name, email';
    const values = [name, email, hashedPassword];
    const result = await pool.query(query, values);
    return result.rows[0];
  },

  // Read
  getAllUsers: async () => {
    const query = 'SELECT id, name, email, created_at FROM users ORDER BY created_at DESC';
    const result = await pool.query(query);
    return result.rows;
  },

  getUserById: async (id) => {
    const query = 'SELECT id, name, email, created_at FROM users WHERE id = $1';
    const result = await pool.query(query, [id]);
    return result.rows[0];
  },

  getUserByEmail: async (email) => {
    const query = 'SELECT * FROM users WHERE email = $1';
    const result = await pool.query(query, [email]);
    return result.rows[0];
  },

  // Update
  updateUser: async (id, name, email) => {
    const query = 'UPDATE users SET name = $1, email = $2 WHERE id = $3 RETURNING id, name, email';
    const result = await pool.query(query, [name, email, id]);
    return result.rows[0];
  },

  // Delete
  deleteUser: async (id) => {
    const query = 'DELETE FROM users WHERE id = $1 RETURNING id';
    const result = await pool.query(query, [id]);
    return result.rows[0];
  }
};

Supabase

const { createClient } = require('@supabase/supabase-js');

const supabaseUrl = process.env.SUPABASE_URL;
const supabaseKey = process.env.SUPABASE_ANON_KEY;
const supabase = createClient(supabaseUrl, supabaseKey);

// CRUD Operations
const supabaseOperations = {
  // Create
  createUser: async (userData) => {
    const { data, error } = await supabase
      .from('users')
      .insert([userData])
      .select();
    
    if (error) throw error;
    return data[0];
  },

  // Read
  getAllUsers: async () => {
    const { data, error } = await supabase
      .from('users')
      .select('*')
      .order('created_at', { ascending: false });
    
    if (error) throw error;
    return data;
  },

  getUserById: async (id) => {
    const { data, error } = await supabase
      .from('users')
      .select('*')
      .eq('id', id)
      .single();
    
    if (error) throw error;
    return data;
  },

  // Update
  updateUser: async (id, updateData) => {
    const { data, error } = await supabase
      .from('users')
      .update(updateData)
      .eq('id', id)
      .select();
    
    if (error) throw error;
    return data[0];
  },

  // Delete
  deleteUser: async (id) => {
    const { data, error } = await supabase
      .from('users')
      .delete()
      .eq('id', id)
      .select();
    
    if (error) throw error;
    return data[0];
  },

  // Advanced queries
  searchUsers: async (searchTerm) => {
    const { data, error } = await supabase
      .from('users')
      .select('*')
      .or(`name.ilike.%${searchTerm}%,email.ilike.%${searchTerm}%`);
    
    if (error) throw error;
    return data;
  }
};

// Real-time subscriptions
const subscribeToUsers = () => {
  const subscription = supabase
    .channel('users')
    .on('postgres_changes', 
      { event: '*', schema: 'public', table: 'users' },
      (payload) => {
        console.log('Change received!', payload);
      }
    )
    .subscribe();
  
  return subscription;
};

API Development

RESTful API Design

// Users Resource
const express = require('express');
const router = express.Router();

// GET /api/users - Get all users
router.get('/', async (req, res) => {
  try {
    const { page = 1, limit = 10, search } = req.query;
    const users = await User.find(search ? {
      $or: [
        { name: { $regex: search, $options: 'i' } },
        { email: { $regex: search, $options: 'i' } }
      ]
    } : {})
    .select('-password')
    .limit(limit * 1)
    .skip((page - 1) * limit)
    .sort({ createdAt: -1 });
    
    const total = await User.countDocuments();
    
    res.json({
      users,
      totalPages: Math.ceil(total / limit),
      currentPage: page,
      total
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// GET /api/users/:id - Get user by id
router.get('/:id', async (req, res) => {
  try {
    const user = await User.findById(req.params.id).select('-password');
    if (!user) {
      return res.status(404).json({ error: 'User not found' });
    }
    res.json(user);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// POST /api/users - Create new user
router.post('/', async (req, res) => {
  try {
    const { name, email, password } = req.body;
    
    // Validation
    if (!name || !email || !password) {
      return res.status(400).json({ error: 'All fields are required' });
    }
    
    // Check if user exists
    const existingUser = await User.findOne({ email });
    if (existingUser) {
      return res.status(409).json({ error: 'User already exists' });
    }
    
    const user = new User({ name, email, password });
    await user.save();
    
    const userResponse = user.toObject();
    delete userResponse.password;
    
    res.status(201).json({
      message: 'User created successfully',
      user: userResponse
    });
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// PUT /api/users/:id - Update user
router.put('/:id', async (req, res) => {
  try {
    const { name, email } = req.body;
    
    const user = await User.findByIdAndUpdate(
      req.params.id,
      { name, email },
      { new: true, runValidators: true }
    ).select('-password');
    
    if (!user) {
      return res.status(404).json({ error: 'User not found' });
    }
    
    res.json({
      message: 'User updated successfully',
      user
    });
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// DELETE /api/users/:id - Delete user
router.delete('/:id', async (req, res) => {
  try {
    const user = await User.findByIdAndDelete(req.params.id);
    if (!user) {
      return res.status(404).json({ error: 'User not found' });
    }
    
    res.json({ message: 'User deleted successfully' });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

module.exports = router;

API Validation

const { body, validationResult } = require('express-validator');

// Validation rules
const userValidationRules = () => {
  return [
    body('name')
      .isLength({ min: 2, max: 50 })
      .withMessage('Name must be between 2 and 50 characters')
      .trim()
      .escape(),
    body('email')
      .isEmail()
      .withMessage('Invalid email format')
      .normalizeEmail(),
    body('password')
      .isLength({ min: 6 })
      .withMessage('Password must be at least 6 characters')
      .matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
      .withMessage('Password must contain uppercase, lowercase, and number')
  ];
};

// Validation middleware
const validate = (req, res, next) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({
      error: 'Validation failed',
      details: errors.array()
    });
  }
  next();
};

// Usage
router.post('/users', userValidationRules(), validate, createUser);

API Documentation with Swagger

const swaggerJsdoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');

const options = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: 'My API',
      version: '1.0.0',
      description: 'A simple Express API'
    },
    servers: [
      {
        url: 'http://localhost:3000',
        description: 'Development server'
      }
    ]
  },
  apis: ['./routes/*.js']
};

const specs = swaggerJsdoc(options);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));

/**
 * @swagger
 * components:
 *   schemas:
 *     User:
 *       type: object
 *       required:
 *         - name
 *         - email
 *       properties:
 *         id:
 *           type: string
 *           description: Auto-generated user ID
 *         name:
 *           type: string
 *           description: User's name
 *         email:
 *           type: string
 *           description: User's email
 */

/**
 * @swagger
 * /api/users:
 *   get:
 *     summary: Get all users
 *     tags: [Users]
 *     parameters:
 *       - in: query
 *         name: page
 *         schema:
 *           type: integer
 *         description: Page number
 *     responses:
 *       200:
 *         description: List of users
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 users:
 *                   type: array
 *                   items:
 *                     $ref: '#/components/schemas/User'
 */

Rate Limiting

const rateLimit = require('express-rate-limit');

// Basic rate limiting
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // limit each IP to 100 requests per windowMs
  message: 'Too many requests from this IP'
});

// Strict rate limiting for auth endpoints
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,
  message: 'Too many authentication attempts'
});

app.use('/api/', limiter);
app.use('/api/auth/', authLimiter);

Authentication & Security

JWT Authentication

const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');

// Generate JWT Token
const generateToken = (userId) => {
  return jwt.sign(
    { userId },
    process.env.JWT_SECRET,
    { expiresIn: '7d' }
  );
};

// Auth Routes
const authRoutes = {
  // Register
  register: async (req, res) => {
    try {
      const { name, email, password } = req.body;
      
      // Check if user exists
      const existingUser = await User.findOne({ email });
      if (existingUser) {
        return res.status(409).json({ error: 'User already exists' });
      }
      
      // Hash password
      const hashedPassword = await bcrypt.hash(password, 12);
      
      // Create user
      const user = new User({
        name,
        email,
        password: hashedPassword
      });
      
      await user.save();
      
      // Generate token
      const token = generateToken(user._id);
      
      res.status(201).json({
        message: 'User created successfully',
        token,
        user: {
          id: user._id,
          name: user.name,
          email: user.email
        }
      });
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  },

  // Login
  login: async (req, res) => {
    try {
      const { email, password } = req.body;
      
      // Find user
      const user = await User.findOne({ email });
      if (!user) {
        return res.status(401).json({ error: 'Invalid credentials' });
      }
      
      // Check password
      const isValidPassword = await bcrypt.compare(password, user.password);
      if (!isValidPassword) {
        return res.status(401).json({ error: 'Invalid credentials' });
      }
      
      // Generate token
      const token = generateToken(user._id);
      
      res.json({
        message: 'Login successful',
        token,
        user: {
          id: user._id,
          name: user.name,
          email: user.email
        }
      });
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  },

  // Get current user
  getMe: async (req, res) => {
    try {
      const user = await User.findById(req.user.userId).select('-password');
      res.json({ user });
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  }
};

// Authentication Middleware
const authenticate = async (req, res, next) => {
  try {
    const token = req.header('Authorization')?.replace('Bearer ', '');
    
    if (!token) {
      return res.status(401).json({ error: 'Access denied, no token provided' });
    }
    
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    const user = await User.findById(decoded.userId);
    
    if (!user) {
      return res.status(401).json({ error: 'Invalid token' });
    }
    
    req.user = decoded;
    next();
  } catch (error) {
    res.status(401).json({ error: 'Invalid token' });
  }
};

// Role-based Authorization
const authorize = (...roles) => {
  return async (req, res, next) => {
    try {
      const user = await User.findById(req.user.userId);
      
      if (!roles.includes(user.role)) {
        return res.status(403).json({ error: 'Access denied' });
      }
      
      next();
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  };
};

// Usage
app.post('/api/auth/register', authRoutes.register);
app.post('/api/auth/login', authRoutes.login);
app.get('/api/auth/me', authenticate, authRoutes.getMe);
app.get('/api/admin', authenticate, authorize('admin'), adminRoutes);

Password Reset

const crypto = require('crypto');
const nodemailer = require('nodemailer');

// Password Reset Schema addition
const userSchema = new mongoose.Schema({
  // ... existing fields
  resetPasswordToken: String,
  resetPasswordExpires: Date
});

// Email transporter
const transporter = nodemailer.createTransporter({
  service: 'gmail',
  auth: {
    user: process.env.EMAIL_USER,
    pass: process.env.EMAIL_PASS
  }
});

const passwordResetRoutes = {
  // Request password reset
  requestReset: async (req, res) => {
    try {
      const { email } = req.body;
      const user = await User.findOne({ email });
      
      if (!user) {
        return res.status(404).json({ error: 'User not found' });
      }
      
      // Generate reset token
      const resetToken = crypto.randomBytes(32).toString('hex');
      user.resetPasswordToken = resetToken;
      user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
      
      await user.save();
      
      // Send email
      const resetUrl = `${process.env.FRONTEND_URL}/reset-password/${resetToken}`;
      
      await transporter.sendMail({
        to: user.email,
        subject: 'Password Reset Request',
        html: `
          <h2>Password Reset Request</h2>
          <p>Click the link below to reset your password:</p>
          <a href="${resetUrl}">Reset Password</a>
        `
      });
      
      res.json({ message: 'Password reset email sent' });
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  },

  // Reset password
  resetPassword: async (req, res) => {
    try {
      const { token, newPassword } = req.body;
      
      const user = await User.findOne({
        resetPasswordToken: token,
        resetPasswordExpires: { $gt: Date.now() }
      });
      
      if (!user) {
        return res.status(400).json({ error: 'Invalid or expired token' });
      }
      
      // Update password
      user.password = await bcrypt.hash(newPassword, 12);
      user.resetPasswordToken = undefined;
      user.resetPasswordExpires = undefined;
      
      await user.save();
      
      res.json({ message: 'Password reset successful' });
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  }
};

Security Best Practices

const helmet = require('helmet');
const cors = require('cors');
const mongoSanitize = require('express-mongo-sanitize');
const xss = require('xss-clean');
const hpp = require('hpp');

// Security middleware
app.use(helmet()); // Set security headers
app.use(cors({
  origin: process.env.FRONTEND_URL,
  credentials: true
}));
app.use(mongoSanitize()); // Prevent NoSQL injection
app.use(xss()); // Clean user input from malicious HTML
app.use(hpp()); // Prevent HTTP Parameter Pollution

// Input sanitization
const sanitizeInput = (input) => {
  if (typeof input === 'string') {
    return input.trim().replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
  }
  return input;
};

// HTTPS redirect (production)
const forceHTTPS = (req, res, next) => {
  if (!req.secure && req.get('x-forwarded-proto') !== 'https') {
    return res.redirect(`https://${req.get('host')}${req.url}`);
  }
  next();
};

// Rate limiting by user
const createAccountLimiter = rateLimit({
  windowMs: 60 * 60 * 1000, // 1 hour
  max: 5, // 5 accounts per hour
  message: 'Too many accounts created from this IP'
});

Testing

Unit Testing with Jest

// __tests__/user.test.js
const User = require('../models/User');
const { createUser, getUserById } = require('../controllers/userController');

// Mock database
jest.mock('../models/User');

describe('User Controller', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('createUser', () => {
    it('should create a new user successfully', async () => {
      const userData = {
        name: 'John Doe',
        email: 'john@example.com',
        password: 'password123'
      };

      const mockUser = { id: '123', ...userData };
      User.prototype.save = jest.fn().mockResolvedValue(mockUser);

      const req = { body: userData };
      const res = {
        status: jest.fn().mockReturnThis(),
        json: jest.fn()
      };

      await createUser(req, res);

      expect(res.status).toHaveBeenCalledWith(201);
      expect(res.json).toHaveBeenCalledWith({
        message: 'User created successfully',
        user: expect.objectContaining({
          name: userData.name,
          email: userData.email
        })
      });
    });

    it('should return error for invalid data', async () => {
      const req = { body: {} };
      const res = {
        status: jest.fn().mockReturnThis(),
        json: jest.fn()
      };

      await createUser(req, res);

      expect(res.status).toHaveBeenCalledWith(400);
      expect(res.json).toHaveBeenCalledWith({
        error: 'All fields are required'
      });
    });
  });
});

// Integration Testing
const request = require('supertest');
const app = require('../app');

describe('User API', () => {
  it('GET /api/users should return all users', async () => {
    const response = await request(app)
      .get('/api/users')
      .expect(200);

    expect(response.body).toHaveProperty('users');
    expect(Array.isArray(response.body.users)).toBe(true);
  });

  it('POST /api/users should create new user', async () => {
    const userData = {
      name: 'Test User',
      email: 'test@example.com',
      password: 'password123'
    };

    const response = await request(app)
      .post('/api/users')
      .send(userData)
      .expect(201);

    expect(response.body.user).toHaveProperty('name', userData.name);
    expect(response.body.user).toHaveProperty('email', userData.email);
    expect(response.body.user).not.toHaveProperty('password');
  });
});

API Testing with Postman/Newman

// package.json scripts
{
  "scripts": {
    "test:api": "newman run postman_collection.json -e postman_environment.json"
  }
}

// Test helper functions
const testHelpers = {
  // Create test user
  createTestUser: async () => {
    const userData = {
      name: 'Test User',
      email: 'test@example.com',
      password: 'password123'
    };
    
    const response = await request(app)
      .post('/api/users')
      .send(userData);
    
    return response.body.user;
  },

  // Get auth token
  getAuthToken: async () => {
    const loginData = {
      email: 'test@example.com',
      password: 'password123'
    };
    
    const response = await request(app)
      .post('/api/auth/login')
      .send(loginData);
    
    return response.body.token;
  },

  // Clean up test data
  cleanup: async () => {
    await User.deleteMany({ email: /test/ });
  }
};

Deployment & DevOps

Environment Configuration

// config/config.js
const config = {
  development: {
    port: process.env.PORT || 3000,
    db: {
      host: process.env.DB_HOST || 'localhost',
      port: process.env.DB_PORT || 27017,
      name: process.env.DB_NAME || 'myapp_dev'
    },
    jwt: {
      secret: process.env.JWT_SECRET || 'dev-secret',
      expiresIn: '7d'
    },
    email: {
      host: process.env.EMAIL_HOST,
      port: process.env.EMAIL_PORT,
      user: process.env.EMAIL_USER,
      pass: process.env.EMAIL_PASS
    }
  },
  production: {
    port: process.env.PORT,
    db: {
      uri: process.env.DATABASE_URL
    },
    jwt: {
      secret: process.env.JWT_SECRET,
      expiresIn: '1d'
    },
    redis: {
      url: process.env.REDIS_URL
    }
  }
};

module.exports = config[process.env.NODE_ENV || 'development'];

Docker Configuration

# Dockerfile
FROM node:18-alpine

WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm ci --only=production

# Copy source code
COPY . .

# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

# Change ownership
RUN chown -R nextjs:nodejs /app
USER nextjs

EXPOSE 3000

CMD ["npm", "start"]
# docker-compose.yml
version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=mongodb://mongo:27017/myapp
      - REDIS_URL=redis://redis:6379
    depends_on:
      - mongo
      - redis
    volumes:
      - ./logs:/app/logs

  mongo:
    image: mongo:5
    volumes:
      - mongo_data:/data/db
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data

volumes:
  mongo_data:
  redis_data:

Process Management with PM2

// ecosystem.config.js
module.exports = {
  apps: [{
    name: 'myapp',
    script: 'server.js',
    instances: 'max',
    exec_mode: 'cluster',
    env: {
      NODE_ENV: 'development'
    },
    env_production: {
      NODE_ENV: 'production',
      PORT: 3000
    },
    error_file: './logs/err.log',
    out_file: './logs/out.log',
    log_file: './logs/combined.log',
    time: true
  }]
};

// package.json scripts
{
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js",
    "pm2:start": "pm2 start ecosystem.config.js --env production",
    "pm2:reload": "pm2 reload ecosystem.config.js --env production",
    "pm2:stop": "pm2 stop ecosystem.config.js",
    "pm2:delete": "pm2 delete ecosystem.config.js"
  }
}

Nginx Configuration

# /etc/nginx/sites-available/myapp
server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

Health Checks and Monitoring

// Health check endpoint
app.get('/health', async (req, res) => {
  try {
    // Check database connection
    await mongoose.connection.db.admin().ping();
    
    // Check Redis connection (if using)
    // await redis.ping();
    
    res.status(200).json({
      status: 'OK',
      timestamp: new Date().toISOString(),
      uptime: process.uptime(),
      memory: process.memoryUsage(),
      database: 'connected'
    });
  } catch (error) {
    res.status(503).json({
      status: 'ERROR',
      error: error.message
    });
  }
});

// Graceful shutdown
const gracefulShutdown = (signal) => {
  console.log(`Received ${signal}. Graceful shutdown...`);
  
  server.close(() => {
    console.log('HTTP server closed.');
    
    mongoose.connection.close(false, () => {
      console.log('MongoDB connection closed.');
      process.exit(0);
    });
  });
};

process.on('SIGTERM', gracefulShutdown);
process.on('SIGINT', gracefulShutdown);

Advanced Concepts

Caching with Redis

const redis = require('redis');
const client = redis.createClient(process.env.REDIS_URL);

// Cache middleware
const cache = (duration = 300) => {
  return async (req, res, next) => {
    const key = `cache:${req.originalUrl}`;
    
    try {
      const cached = await client.get(key);
      if (cached) {
        return res.json(JSON.parse(cached));
      }
      
      // Store original res.json
      const originalJson = res.json;
      
      res.json = function(data) {
        // Cache the response
        client.setex(key, duration, JSON.stringify(data));
        
        // Call original json method
        originalJson.call(this, data);
      };
      
      next();
    } catch (error) {
      next();
    }
  };
};

// Usage
app.get('/api/users', cache(600), getAllUsers);

// Cache invalidation
const invalidateCache = (pattern) => {
  return async (req, res, next) => {
    try {
      const keys = await client.keys(pattern);
      if (keys.length > 0) {
        await client.del(keys);
      }
    } catch (error) {
      console.error('Cache invalidation error:', error);
    }
    next();
  };
};

// Invalidate user cache after operations
app.post('/api/users', invalidateCache('cache:/api/users*'), createUser);

File Upload Handling

const multer = require('multer');
const path = require('path');
const fs = require('fs').promises;

// Storage configuration
const storage = multer.diskStorage({
  destination: async (req, file, cb) => {
    const uploadPath = 'uploads/';
    try {
      await fs.mkdir(uploadPath, { recursive: true });
      cb(null, uploadPath);
    } catch (error) {
      cb(error);
    }
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
  }
});

// File filter
const fileFilter = (req, file, cb) => {
  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
  
  if (allowedTypes.includes(file.mimetype)) {
    cb(null, true);
  } else {
    cb(new Error('Invalid file type'), false);
  }
};

const upload = multer({
  storage,
  fileFilter,
  limits: {
    fileSize: 5 * 1024 * 1024 // 5MB
  }
});

// Upload routes
app.post('/api/upload/single', upload.single('image'), (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: 'No file uploaded' });
  }
  
  res.json({
    message: 'File uploaded successfully',
    file: {
      filename: req.file.filename,
      originalname: req.file.originalname,
      mimetype: req.file.mimetype,
      size: req.file.size
    }
  });
});

app.post('/api/upload/multiple', upload.array('images', 5), (req, res) => {
  if (!req.files || req.files.length === 0) {
    return res.status(400).json({ error: 'No files uploaded' });
  }
  
  const files = req.files.map(file => ({
    filename: file.filename,
    originalname: file.originalname,
    mimetype: file.mimetype,
    size: file.size
  }));
  
  res.json({
    message: 'Files uploaded successfully',
    files
  });
});

WebSocket Implementation

const http = require('http');
const socketIo = require('socket.io');

const server = http.createServer(app);
const io = socketIo(server, {
  cors: {
    origin: process.env.FRONTEND_URL,
    methods: ["GET", "POST"]
  }
});

// Socket authentication middleware
io.use(async (socket, next) => {
  try {
    const token = socket.handshake.auth.token;
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    const user = await User.findById(decoded.userId);
    
    socket.user = user;
    next();
  } catch (error) {
    next(new Error('Authentication error'));
  }
});

// Socket connection handling
io.on('connection', (socket) => {
  console.log(`User ${socket.user.name} connected`);
  
  // Join user to their room
  socket.join(`user_${socket.user._id}`);
  
  // Handle chat messages
  socket.on('send_message', async (data) => {
    try {
      const message = new Message({
        sender: socket.user._id,
        content: data.content,
        room: data.room
      });
      
      await message.save();
      
      // Broadcast to room
      socket.to(data.room).emit('new_message', {
        id: message._id,
        content: message.content,
        sender: {
          id: socket.user._id,
          name: socket.user.name
        },
        timestamp: message.createdAt
      });
    } catch (error) {
      socket.emit('error', { message: error.message });
    }
  });
  
  // Handle disconnect
  socket.on('disconnect', () => {
    console.log(`User ${socket.user.name} disconnected`);
  });
});

server.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Background Jobs with Bull Queue

const Queue = require('bull');
const nodemailer = require('nodemailer');

// Create queues
const emailQueue = new Queue('email processing', process.env.REDIS_URL);
const imageQueue = new Queue('image processing', process.env.REDIS_URL);

// Email job processor
emailQueue.process(async (job) => {
  const { to, subject, html } = job.data;
  
  const transporter = nodemailer.createTransporter({
    // email config
  });
  
  await transporter.sendMail({
    from: process.env.FROM_EMAIL,
    to,
    subject,
    html
  });
  
  return { sent: true };
});

// Image processing job
imageQueue.process(async (job) => {
  const { imagePath, sizes } = job.data;
  
  // Process image with sharp or similar
  const sharp = require('sharp');
  
  for (const size of sizes) {
    await sharp(imagePath)
      .resize(size.width, size.height)
      .toFile(`processed/${size.name}_${path.basename(imagePath)}`);
  }
  
  return { processed: true };
});

// Add jobs to queue
const sendWelcomeEmail = async (userEmail, userName) => {
  await emailQueue.add('welcome email', {
    to: userEmail,
    subject: 'Welcome!',
    html: `<h1>Welcome ${userName}!</h1>`
  });
};

const processUserImage = async (imagePath) => {
  await imageQueue.add('resize image', {
    imagePath,
    sizes: [
      { name: 'thumbnail', width: 150, height: 150 },
      { name: 'medium', width: 500, height: 500 }
    ]
  });
};

// Queue monitoring
emailQueue.on('completed', (job) => {
  console.log(`Email job ${job.id} completed`);
});

emailQueue.on('failed', (job, err) => {
  console.error(`Email job ${job.id} failed:`, err);
});

Database Migrations

// migrations/001_create_users_table.js
const mongoose = require('mongoose');

const up = async () => {
  // Create indexes
  await mongoose.connection.collection('users').createIndex({ email: 1 }, { unique: true });
  await mongoose.connection.collection('users').createIndex({ createdAt: -1 });
};

const down = async () => {
  // Drop indexes
  await mongoose.connection.collection('users').dropIndex({ email: 1 });
  await mongoose.connection.collection('users').dropIndex({ createdAt: -1 });
};

module.exports = { up, down };

// Migration runner
const runMigrations = async () => {
  const migrations = [
    require('./migrations/001_create_users_table'),
    // Add more migrations
  ];
  
  for (const migration of migrations) {
    try {
      await migration.up();
      console.log(`Migration ${migration.name} completed`);
    } catch (error) {
      console.error(`Migration ${migration.name} failed:`, error);
      break;
    }
  }
};

Logging

const winston = require('winston');

// Configure logger
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  defaultMeta: { service: 'api' },
  transports: [
    new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
    new winston.transports.File({ filename: 'logs/combined.log' }),
  ],
});

if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: winston.format.simple()
  }));
}

// Request logging middleware
const requestLogger = (req, res, next) => {
  const start = Date.now();
  
  res.on('finish', () => {
    const duration = Date.now() - start;
    logger.info({
      method: req.method,
      url: req.url,
      status: res.statusCode,
      duration: `${duration}ms`,
      userAgent: req.get('User-Agent'),
      ip: req.ip
    });
  });
  
  next();
};

app.use(requestLogger);

// Usage in routes
app.get('/api/users', async (req, res) => {
  try {
    logger.info('Fetching users');
    const users = await User.find();
    res.json(users);
  } catch (error) {
    logger.error('Error fetching users', { error: error.message, stack: error.stack });
    res.status(500).json({ error: 'Internal server error' });
  }
});

Quick Reference Commands

NPM Commands

# Initialize project
npm init -y

# Install dependencies
npm install express mongoose dotenv
npm install -D nodemon jest

# Run scripts
npm start
npm run dev
npm test

# Update packages
npm update
npm audit fix

Git Commands

# Initialize repository
git init
git add .
git commit -m "Initial commit"

# Create and switch branches
git checkout -b feature/api-endpoints
git push -u origin feature/api-endpoints

# Merge changes
git checkout main
git merge feature/api-endpoints

Docker Commands

# Build image
docker build -t myapp .

# Run container
docker run -p 3000:3000 myapp

# Docker compose
docker-compose up -d
docker-compose down
docker-compose logs -f

Database Commands

# MongoDB
mongosh
use myapp
db.users.find()
db.users.createIndex({ email: 1 }, { unique: true })

# PostgreSQL
psql -U username -d database
\dt
SELECT * FROM users;
CREATE INDEX idx_users_email ON users(email);

This comprehensive cheatsheet covers all essential backend development concepts from beginner to advanced levels. Use it as a reference guide for building robust, scalable backend applications with modern technologies and best practices.