Building Scalable APIs with Node.js and Express
    Web Development

    Building Scalable APIs with Node.js and Express

    15 دقيقة قراءة
    423 41

    Introduction

    Building a robust and scalable API is the foundation of any modern application. In this article, we will explore the best practices for building APIs using Node.js and Express.

    Project Structure

    src/
    ├── controllers/     # Business logic
    ├── routes/          # Route definitions
    ├── middleware/      # Middleware
    ├── models/          # Database models
    ├── services/        # External services
    ├── utils/           # Utility functions
    └── app.js           # Entry point
    

    Error Handling

    class AppError extends Error {
      constructor(message, statusCode) {
        super(message);
        this.statusCode = statusCode;
        this.isOperational = true;
      }
    }
    
    const errorHandler = (err, req, res, next) => {
      const statusCode = err.statusCode || 500;
      res.status(statusCode).json({
        success: false,
        error: {
          message: err.message,
          code: err.code || 'INTERNAL_ERROR'
        }
      });
    };
    

    Data Validation

    Use libraries like Zod or Joi for validation:

    const { z } = require('zod');
    
    const userSchema = z.object({
      email: z.string().email(),
      password: z.string().min(8),
      name: z.string().min(2).max(100)
    });
    
    const validateUser = (req, res, next) => {
      try {
        userSchema.parse(req.body);
        next();
      } catch (error) {
        res.status(400).json({ errors: error.errors });
      }
    };
    

    Caching

    Use Redis for caching:

    const redis = require('redis');
    const client = redis.createClient();
    
    const cacheMiddleware = async (req, res, next) => {
      const key = req.originalUrl;
      const cached = await client.get(key);
      
      if (cached) {
        return res.json(JSON.parse(cached));
      }
      
      res.originalJson = res.json;
      res.json = (data) => {
        client.setEx(key, 3600, JSON.stringify(data));
        res.originalJson(data);
      };
      
      next();
    };
    

    Rate Limiting

    const rateLimit = require('express-rate-limit');
    
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minutes
      max: 100, // 100 requests per IP
      message: { error: 'Too many requests, please try again later' }
    });
    
    app.use('/api/', limiter);
    

    Monitoring and Logging

    const winston = require('winston');
    
    const logger = winston.createLogger({
      level: 'info',
      format: winston.format.json(),
      transports: [
        new winston.transports.File({ filename: 'error.log', level: 'error' }),
        new winston.transports.File({ filename: 'combined.log' })
      ]
    });
    

    Conclusion

    Building a scalable API requires good planning and adherence to best practices. Focus on:

    • Clear project structure
    • Comprehensive error handling
    • Input validation
    • Caching
    • Continuous monitoring