Workstation Logo
পণ্য
এআই ল্যাবসOpenAI এজেন্টClaude এজেন্টGrok BotWorkstation CRM (WSL CRM)মার্কেটিংসব পণ্য
এআই সমাধান
এআই ওয়ার্কস্টেশনAI SME Packagesপ্রাইভেট এআইজিপিইউ ক্লাস্টারএজ এআইএন্টারপ্রাইজ এআই ল্যাবশিল্প অনুযায়ী এআই
সেবাসমূহ
Platform ModernisationDigital EngineeringData Foundations & AIAutonomous Operationsএআই পরামর্শDevOps অটোমেশনসাইবার নিরাপত্তাসফটওয়্যার ডেভেলপমেন্টএজেন্ট নির্মাণMLOps সেটআপ
আমাদের সম্পর্কে
অংশীদারগ্রাহক গল্প
প্রবন্ধ
ডকুমেন্টেশন
WSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7
ব্লগ
যোগাযোগ করুনLogin
Workstation

আধুনিক ব্যবসার জন্য AI ওয়ার্কস্টেশন, AI মাল্টি-এজেন্টিক সফটওয়্যার, GPU অবকাঠামো এবং বুদ্ধিমান এজেন্ট সমাধান।

যোগাযোগ করুন

AI সমাধান

এআই ওয়ার্কস্টেশনAI SME Packagesপ্রাইভেট এআইজিপিইউ ক্লাস্টারএজ এআইএন্টারপ্রাইজ এআই ল্যাবশিল্প অনুযায়ী এআই

পণ্য

সব পণ্যWSL CRM ও ERPমার্কেটিংOpenAI এজেন্টWSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7

কোম্পানি

আমাদের সম্পর্কেকেন Workstationঅংশীদারগ্রাহক গল্পমূল্যযোগাযোগ

রিসোর্স

প্রবন্ধডকুমেন্টেশনব্লগখুঁজুনসাইটম্যাপ
যুক্তরাজ্য অফিস
77-79 Marlowes, Hemel Hempstead HP1 1LFদিকনির্দেশ - M25 আউটার লন্ডন থেকে জংশন ২০ নিনকোম্পানি নং: 11641870সোম - শুক্র: সকাল ৯:০০ - সন্ধ্যা ৬:০০ GMT
+44 7515 356 146
বেলজিয়াম অফিস
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683সোম - শুক্র: সকাল ৯:০০ - সন্ধ্যা ৬:০০ CET
+32 492 45 67 46
ভারত অফিস
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841

© 2026 Workstation AI। সর্বস্বত্ব সংরক্ষিত।

গোপনীয়তাকুকিসেবার শর্তাবলীওয়েবসাইট সাইটম্যাপ

Loading blog...

Home / Blog
WebFrontendReact

Node.js এবং MySQL সহ শক্তিশালী ব্যাকএন্ড সিস্টেম তৈরি করা

Node.js, Express, এবং MySQL সহ স্কেলযোগ্য, সুরক্ষিত ব্যাকএন্ড API ডিজাইন এবং বাস্তবায়ন

Balinder Walia২৭ মে, ২০২৫11 min read

Node.js এবং MySQL ব্যাকএন্ড সিস্টেম তৈরির জন্য সবচেয়ে নির্ভরযোগ্য এবং যুদ্ধ-পরীক্ষিত সমন্বয়গুলির মধ্যে একটি। Node.js একটি ইভেন্ট-চালিত, নন-ব্লকিং I/O মডেল সরবরাহ করে যা সমবর্তী অনুরোধগুলিকে দক্ষতার সাথে পরিচালনা করে, যখন MySQL ব্যবসায়িক অ্যাপ্লিকেশনগুলির চাহিদা সম্পর্কিত সম্পর্কিত ডেটা অখণ্ডতা সরবরাহ করে। একসাথে, তারা একটি ভিত্তি তৈরি করে যা স্টার্টআপ এমভিপি থেকে শুরু করে এন্টারপ্রাইজ প্ল্যাটফর্ম পর্যন্ত প্রতিদিন লক্ষাধিক অনুরোধ পরিচালনা করে।

এই নির্দেশিকাটি একটি প্রোডাকশন-গ্রেড ব্যাকএন্ড API নির্মাণের মধ্য দিয়ে চলে, প্রকল্পের কাঠামো, ডাটাবেস ডিজাইন, প্রমাণীকরণ, ত্রুটি পরিচালনা এবং স্থাপনার অন্তর্ভুক্ত।

Express.js প্রোজেক্ট স্ট্রাকচার

Node.js + এক্সপ্রেস ব্যাকএন্ড আর্কিটেকচার

মিডলওয়্যার

20 লাএ Auth (JWT)যাচাইকরণহারের সীমাCORSHelmetক্লায়েন্ট 37X 37X ক্লায়েন্ট Loggedব্রাউজার / অ্যাপAPIগেটওয়ে/api/v1এক্সপ্রেসরুটগুলি রুটগুলি X6PO/G55PUTXকন্ট্রোলারঅনুরোধ পরিচালনাপরিষেবাগুলিব্যবসায়িক যুক্তিMySQLরিলেশনাল DB X77 রিলেশনাল ডিবি X7HTTPরুটকলকলক্যোয়ারীক্যোয়ারী উত্তর XTAG93 ম্যাট সাফল্যের জন্য সত্য,ডেটা: [...],পৃষ্ঠা সংখ্যা: {...}}পাইপলাইন হ্যান্ডলিং ত্রুটিX1TAG101rr 108XasyncHandlererrorHandlerকেন্দ্রীভূত, সামঞ্জস্যপূর্ণ ত্রুটি প্রতিক্রিয়া
একটি প্রজেক্টের ভালভাবে রক্ষণাবেক্ষণ করা যায়-একটি XTAG24-এর কাঠামো বজায় রাখা যায়৷ উদ্বেগগুলিকে স্পষ্টভাবে আলাদা করুন এবং তাড়াতাড়ি সম্মেলনগুলি স্থাপন করুন।

project-root/
  src/
    config/
      database.js
      environment.js
      logger.js
    middleware/
      auth.js
      errorHandler.js
      rateLimiter.js
      validator.js
    models/
      User.js
      Product.js
      Order.js
      index.js
    routes/
      auth.routes.js
      users.routes.js
      products.routes.js
      orders.routes.js
      index.js
    services/
      auth.service.js
      user.service.js
      product.service.js
      email.service.js
    utils/
      ApiError.js
      asyncHandler.js
      pagination.js
    app.js
    server.js
  migrations/
  seeders/
  tests/
  .env
  .env.example
  package.json

এন্ট্রি পয়েন্ট অপরিহার্য মিডলওয়্যারের সাথে এক্সপ্রেস সেট আপ করে:

// src/app.js
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const { errorHandler } = require('./middleware/errorHandler');
const routes = require('./routes');

const app = express();

// Security middleware
app.use(helmet());
app.use(cors({
  origin: process.env.ALLOWED_ORIGINS?.split(',') || 'http://localhost:3000',
  credentials: true,
}));

// Request parsing
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));

// Logging
app.use(morgan(process.env.NODE_ENV === 'production' ? 'combined' : 'dev'));

// Health check
app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

// API routes
app.use('/api/v1', routes);

// Error handling (must be last)
app.use(errorHandler);

module.exports = app;

RESTful API ডিজাইন

আপনার API শেষ পয়েন্টগুলিকে REST কনভেনশন অনুসরণ করে ডিজাইন করুন৷ সম্পদের জন্য বিশেষ্য, কর্মের জন্য HTTP পদ্ধতি এবং ধারাবাহিক প্রতিক্রিয়া বিন্যাস ব্যবহার করুন।

// src/routes/products.routes.js
const router = require('express').Router();
const { authenticate, authorize } = require('../middleware/auth');
const { validate } = require('../middleware/validator');
const { createProductSchema, updateProductSchema } = require('../validators/product');
const productController = require('../controllers/product.controller');

router.get('/', productController.getAll);
router.get('/:id', productController.getById);
router.post('/',
  authenticate,
  authorize('admin'),
  validate(createProductSchema),
  productController.create
);
router.put('/:id',
  authenticate,
  authorize('admin'),
  validate(updateProductSchema),
  productController.update
);
router.delete('/:id',
  authenticate,
  authorize('admin'),
  productController.delete
);

module.exports = router;

কন্ট্রোলারগুলি পাতলা হওয়া উচিত, পরিষেবা ক্লাসে ব্যবসায়িক যুক্তি অর্পণ করা উচিত:

// src/controllers/product.controller.js
const productService = require('../services/product.service');
const { asyncHandler } = require('../utils/asyncHandler');

exports.getAll = asyncHandler(async (req, res) => {
  const { page = 1, limit = 20, sort = 'created_at', order = 'DESC', search } = req.query;

  const result = await productService.findAll({
    page: parseInt(page),
    limit: Math.min(parseInt(limit), 100),
    sort,
    order,
    search,
  });

  res.json({
    success: true,
    data: result.products,
    pagination: {
      page: result.page,
      limit: result.limit,
      total: result.total,
      totalPages: result.totalPages,
    },
  });
});

exports.create = asyncHandler(async (req, res) => {
  const product = await productService.create(req.body);
  res.status(201).json({
    success: true,
    data: product,
  });
});

MySQL কানেকশন পুলিং এর সাথে mysql2

MySQL কানেকশন পুল আর্কিটেকচারঅ্যাপ্লিকেশানসমবর্তী অনুরোধগুলিথ্রেড অনুরোধঅনুরোধ থ্রেড 2অনুরোধ থ্রেড 3অনুরোধ থ্রেড 4...অনুরোধ থ্রেড Nসংযোগ পুল (mysql2)সক্রিয়নিষ্ক্রিয় সংযোগ XTAG1818 XTAG1818 — সক্রিয়সংযোগ 2 — সক্রিয়সংযোগ 3 — সক্রিয়সংযোগ 4 — নিষ্ক্রিয়XTAG19 I সংযোগসংযোগ সীমা: 10 | waitForConnections: trueenableKeepAlive: true | সারি সীমা: 0MySQLডেটাবেস সার্ভারডেটা স্টোরInnoDB ইঞ্জিনTAG230T সংযোগগুলি পুনঃব্যবহার করে, প্রতি অনুরোধে নতুনগুলি তৈরি করার ওভারহেড এড়িয়ে যায়

সংযোগ পুলিং কার্যক্ষমতার জন্য গুরুত্বপূর্ণ৷mysql2প্যাকেজটি একটি প্রতিশ্রুতি-ভিত্তিক API প্রদান করে প্রস্তুত বিবৃতি এবং বাক্সের বাইরে সংযোগ পুলিং সহ।

// src/config/database.js
const mysql = require('mysql2/promise');
const logger = require('./logger');

const pool = mysql.createPool({
  host: process.env.DB_HOST || 'localhost',
  port: parseInt(process.env.DB_PORT) || 3306,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  waitForConnections: true,
  connectionLimit: parseInt(process.env.DB_POOL_SIZE) || 10,
  queueLimit: 0,
  enableKeepAlive: true,
  keepAliveInitialDelay: 30000,
  timezone: '+00:00',
  typeCast: function (field, next) {
    if (field.type === 'TINY' && field.length === 1) {
      return field.string() === '1';
    }
    return next();
  },
});

// Test connection on startup
pool.getConnection()
  .then(conn => {
    logger.info('MySQL connected successfully');
    conn.release();
  })
  .catch(err => {
    logger.error('MySQL connection failed:', err.message);
    process.exit(1);
  });

module.exports = pool;

SQL ইনজেকশন প্রতিরোধ করার জন্য সর্বদা প্যারামিটারাইজড ক্যোয়ারী ব্যবহার করুন:

// NEVER do this
const query = `SELECT * FROM users WHERE email = '${email}'`;

// ALWAYS use parameterized queries
const [rows] = await pool.execute(
  'SELECT id, email, first_name, last_name FROM users WHERE email = ?',
  [email]
);

সিক্যুয়েলাইজ ORM

জটিল ডেটা সম্পর্কযুক্ত অ্যাপ্লিকেশনগুলির জন্য, সিক্যুয়েলাইজ একটি পূর্ণ বৈশিষ্ট্যযুক্ত, মডেল এবং সংজ্ঞার সাথে ওআরএম-এর সংজ্ঞা প্রদান করে। ভবন JWT

এর সাথে

// src/models/Product.js
const { DataTypes } = require('sequelize');
const sequelize = require('../config/sequelize');

const Product = sequelize.define('Product', {
  id: {
    type: DataTypes.UUID,
    defaultValue: DataTypes.UUIDV4,
    primaryKey: true,
  },
  name: {
    type: DataTypes.STRING(255),
    allowNull: false,
    validate: {
      notEmpty: true,
      len: [2, 255],
    },
  },
  description: {
    type: DataTypes.TEXT,
    allowNull: true,
  },
  price: {
    type: DataTypes.DECIMAL(10, 2),
    allowNull: false,
    validate: {
      min: 0,
    },
  },
  sku: {
    type: DataTypes.STRING(100),
    unique: true,
    allowNull: false,
  },
  stock_quantity: {
    type: DataTypes.INTEGER,
    defaultValue: 0,
    validate: {
      min: 0,
    },
  },
  is_active: {
    type: DataTypes.BOOLEAN,
    defaultValue: true,
  },
}, {
  tableName: 'products',
  timestamps: true,
  underscored: true,
  paranoid: true, // Soft deletes
  indexes: [
    { fields: ['sku'], unique: true },
    { fields: ['is_active'] },
    { fields: ['price'] },
    { fields: ['created_at'] },
  ],
});

// Associations
Product.associate = (models) => {
  Product.belongsTo(models.Category, { foreignKey: 'category_id' });
  Product.hasMany(models.OrderItem, { foreignKey: 'product_id' });
  Product.belongsToMany(models.Tag, { through: 'product_tags' });
};

module.exports = Product;

প্রমাণীকরণ JSON ওয়েব টোকেন ব্যবহার করে স্টেটলেস প্রমাণীকরণ প্রয়োগ করুন। API অনুরোধের জন্য অ্যাক্সেস টোকেন ব্যবহার করুন এবং সেশন পরিচালনার জন্য টোকেন রিফ্রেশ করুন।

// src/services/auth.service.js
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const { User } = require('../models');
const ApiError = require('../utils/ApiError');

const SALT_ROUNDS = 12;
const ACCESS_TOKEN_EXPIRY = '15m';
const REFRESH_TOKEN_EXPIRY = '7d';

exports.register = async ({ email, password, firstName, lastName }) => {
  const existingUser = await User.findOne({ where: { email } });
  if (existingUser) {
    throw new ApiError(409, 'Email already registered');
  }

  const hashedPassword = await bcrypt.hash(password, SALT_ROUNDS);
  const user = await User.create({
    email,
    password: hashedPassword,
    first_name: firstName,
    last_name: lastName,
  });

  const tokens = generateTokens(user);
  return { user: sanitizeUser(user), ...tokens };
};

exports.login = async ({ email, password }) => {
  const user = await User.findOne({ where: { email } });
  if (!user || !(await bcrypt.compare(password, user.password))) {
    throw new ApiError(401, 'Invalid email or password');
  }

  const tokens = generateTokens(user);
  return { user: sanitizeUser(user), ...tokens };
};

function generateTokens(user) {
  const accessToken = jwt.sign(
    { userId: user.id, email: user.email, role: user.role },
    process.env.JWT_SECRET,
    { expiresIn: ACCESS_TOKEN_EXPIRY }
  );

  const refreshToken = jwt.sign(
    { userId: user.id, tokenType: 'refresh' },
    process.env.JWT_REFRESH_SECRET,
    { expiresIn: REFRESH_TOKEN_EXPIRY }
  );

  return { accessToken, refreshToken };
}

function sanitizeUser(user) {
  const { password, ...userData } = user.toJSON();
  return userData;
}

প্রমাণীকরণ মিডলওয়্যার সুরক্ষিত রুটে টোকেন যাচাই করে:

// src/middleware/auth.js
const jwt = require('jsonwebtoken');
const ApiError = require('../utils/ApiError');

exports.authenticate = (req, res, next) => {
  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith('Bearer ')) {
    throw new ApiError(401, 'Access token required');
  }

  const token = authHeader.split(' ')[1];
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (error) {
    if (error.name === 'TokenExpiredError') {
      throw new ApiError(401, 'Access token expired');
    }
    throw new ApiError(401, 'Invalid access token');
  }
};

exports.authorize = (...roles) => {
  return (req, res, next) => {
    if (!roles.includes(req.user.role)) {
      throw new ApiError(403, 'Insufficient permissions');
    }
    next();
  };
};

জয়ের সাথে ইনপুট বৈধতা

আপনার ব্যবসার যুক্তিতে পৌঁছানোর আগে সমস্ত আগত ডেটা যাচাই করুন৷ Joi একটি শক্তিশালী স্কিমা-ভিত্তিক বৈধতা লাইব্রেরি প্রদান করে।

// src/validators/product.js
const Joi = require('joi');

exports.createProductSchema = Joi.object({
  name: Joi.string().min(2).max(255).required(),
  description: Joi.string().max(5000).optional(),
  price: Joi.number().positive().precision(2).required(),
  sku: Joi.string().alphanum().max(100).required(),
  stock_quantity: Joi.number().integer().min(0).default(0),
  category_id: Joi.string().uuid().required(),
  tags: Joi.array().items(Joi.string().uuid()).optional(),
  is_active: Joi.boolean().default(true),
});

exports.updateProductSchema = Joi.object({
  name: Joi.string().min(2).max(255),
  description: Joi.string().max(5000).allow(null),
  price: Joi.number().positive().precision(2),
  stock_quantity: Joi.number().integer().min(0),
  category_id: Joi.string().uuid(),
  is_active: Joi.boolean(),
}).min(1);

// src/middleware/validator.js
exports.validate = (schema) => {
  return (req, res, next) => {
    const { error, value } = schema.validate(req.body, {
      abortEarly: false,
      stripUnknown: true,
    });

    if (error) {
      const errors = error.details.map(detail => ({
        field: detail.path.join('.'),
        message: detail.message,
      }));
      return res.status(400).json({
        success: false,
        message: 'Validation failed',
        errors,
      });
    }

    req.body = value;
    next();
  };
};

ত্রুটি হ্যান্ডলিং মিডলওয়্যার

কেন্দ্রীভূত ত্রুটি হ্যান্ডলিং সামঞ্জস্যপূর্ণ ত্রুটি প্রতিক্রিয়া নিশ্চিত করে এবং ক্লায়েন্টদের কাছে সংবেদনশীল তথ্য ফাঁস হতে বাধা দেয়৷

// src/utils/ApiError.js
class ApiError extends Error {
  constructor(statusCode, message, errors = []) {
    super(message);
    this.statusCode = statusCode;
    this.errors = errors;
    this.isOperational = true;
    Error.captureStackTrace(this, this.constructor);
  }
}

module.exports = ApiError;

// src/utils/asyncHandler.js
exports.asyncHandler = (fn) => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch(next);
};

// src/middleware/errorHandler.js
const logger = require('../config/logger');

exports.errorHandler = (err, req, res, next) => {
  let statusCode = err.statusCode || 500;
  let message = err.message || 'Internal Server Error';

  // Sequelize validation errors
  if (err.name === 'SequelizeValidationError') {
    statusCode = 400;
    message = 'Validation error';
  }

  // Sequelize unique constraint
  if (err.name === 'SequelizeUniqueConstraintError') {
    statusCode = 409;
    message = 'Resource already exists';
  }

  // Log server errors
  if (statusCode >= 500) {
    logger.error({
      message: err.message,
      stack: err.stack,
      url: req.originalUrl,
      method: req.method,
      ip: req.ip,
    });
  }

  res.status(statusCode).json({
    success: false,
    message,
    ...(process.env.NODE_ENV === 'development' && { stack: err.stack }),
    ...(err.errors?.length && { errors: err.errors }),
  });
};

ক্যোয়ারী অপ্টিমাইজেশান এবং ইন্ডেক্সিং

দক্ষ ডাটাবেস প্রশ্নগুলি ব্যাকএন্ড পারফরম্যান্সের জন্য অত্যন্ত গুরুত্বপূর্ণ৷ আপনার MySQL প্রশ্নগুলি দ্রুত রাখতে এই কৌশলগুলি অনুসরণ করুন৷

  • ঘন ঘন জিজ্ঞাসা করা কলামগুলিতে সূচী ব্যবহার করুন- WHERE ক্লজ, যোগদানের শর্তাবলী এবং ORDER BY বিবৃতিতে ব্যবহৃত কলামগুলিতে সূচী যোগ করুন। যৌগিক সূচী বাম উপসর্গ নিয়ম অনুসরণ করা উচিত.
  • এড়িয়ে চলুন SELECT *- আপনার প্রয়োজনীয় কলামগুলি সর্বদা নির্দিষ্ট করুন৷ এটি ডেটা স্থানান্তর হ্রাস করে এবং MySQL কে কভারিং সূচক ব্যবহার করার অনুমতি দেয়।
  • প্রশ্নগুলি বিশ্লেষণ করতে ব্যাখ্যা করুন- এক্সিকিউশন প্ল্যান বোঝার জন্য আপনার প্রশ্নের আগেEXPLAINচালান৷ সম্পূর্ণ টেবিল স্ক্যান, ফাইলসর্ট অপারেশন এবং অস্থায়ী টেবিলের জন্য দেখুন।
  • অপ্টিমাইজ পেজিনেশন- বড় ডেটাসেটের জন্য, অফসেটের পরিবর্তে কার্সার-ভিত্তিক পেজিনেশন (কীসেট পেজিনেশন) ব্যবহার করুন, যা উচ্চ পৃষ্ঠা সংখ্যায় ধীর হয়ে যায়।
// Inefficient OFFSET pagination
const [rows] = await pool.execute(
  'SELECT * FROM products ORDER BY created_at DESC LIMIT ? OFFSET ?',
  [limit, (page - 1) * limit]
);

// Efficient cursor-based pagination
const [rows] = await pool.execute(
  `SELECT id, name, price, created_at FROM products
   WHERE created_at < ?
   ORDER BY created_at DESC
   LIMIT ?`,
  [cursor, limit]
);

ডাটাবেস মাইগ্রেশন

কখনও ম্যানুয়ালি প্রোডাকশন ডাটাবেস পরিবর্তন করবেন না৷ সংস্করণ-নিয়ন্ত্রিত স্কিমা পরিবর্তনের জন্য সিক্যুয়ালাইজ মাইগ্রেশন ব্যবহার করুন।

// migrations/20250101000000-create-products-table.js
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('products', {
      id: {
        type: Sequelize.UUID,
        defaultValue: Sequelize.UUIDV4,
        primaryKey: true,
      },
      name: {
        type: Sequelize.STRING(255),
        allowNull: false,
      },
      price: {
        type: Sequelize.DECIMAL(10, 2),
        allowNull: false,
      },
      sku: {
        type: Sequelize.STRING(100),
        unique: true,
        allowNull: false,
      },
      category_id: {
        type: Sequelize.UUID,
        references: {
          model: 'categories',
          key: 'id',
        },
        onUpdate: 'CASCADE',
        onDelete: 'SET NULL',
      },
      created_at: {
        type: Sequelize.DATE,
        defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
      },
      updated_at: {
        type: Sequelize.DATE,
        defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'),
      },
    });

    await queryInterface.addIndex('products', ['sku']);
    await queryInterface.addIndex('products', ['category_id']);
    await queryInterface.addIndex('products', ['created_at']);
  },

  down: async (queryInterface) => {
    await queryInterface.dropTable('products');
  },
};

হার সীমাবদ্ধতা

হার সীমিত করে অপব্যবহার থেকে আপনার API কে রক্ষা করুন৷ বিতরণ করা স্থাপনার জন্য একটি Redis স্টোরের সাথেexpress-rate-limitব্যবহার করুন।

// src/middleware/rateLimiter.js
const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const redis = require('../config/redis');

exports.apiLimiter = rateLimit({
  store: new RedisStore({ sendCommand: (...args) => redis.call(...args) }),
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100,
  message: {
    success: false,
    message: 'Too many requests, please try again later',
  },
  standardHeaders: true,
  legacyHeaders: false,
});

exports.authLimiter = rateLimit({
  store: new RedisStore({ sendCommand: (...args) => redis.call(...args) }),
  windowMs: 15 * 60 * 1000,
  max: 5,
  message: {
    success: false,
    message: 'Too many login attempts, please try again later',
  },
  skipSuccessfulRequests: true,
});

Winston এর সাথে লগিং

প্রোডাকশন অ্যাপ্লিকেশানগুলির একাধিক পরিবহন এবং লগ লেভেল সহ কাঠামোবদ্ধ লগিং প্রয়োজন৷

// src/config/logger.js
const winston = require('winston');

const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  defaultMeta: { service: 'api-server' },
  transports: [
    new winston.transports.File({
      filename: 'logs/error.log',
      level: 'error',
      maxsize: 5242880, // 5MB
      maxFiles: 5,
    }),
    new winston.transports.File({
      filename: 'logs/combined.log',
      maxsize: 5242880,
      maxFiles: 10,
    }),
  ],
});

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

module.exports = logger;

Docker স্থাপনা

পরিবেশ জুড়ে সামঞ্জস্যপূর্ণ স্থাপনার জন্য আপনার আবেদন ধারণ করুন৷

# Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:20-alpine
WORKDIR /app
RUN addgroup -g 1001 -S appgroup && \
    adduser -S appuser -u 1001 -G appgroup
COPY --from=builder /app/node_modules ./node_modules
COPY src/ ./src/
COPY migrations/ ./migrations/
COPY package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["node", "src/server.js"]
# docker-compose.yml
version: '3.8'
services:
  api:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DB_HOST=mysql
      - DB_USER=app_user
      - DB_PASSWORD_FILE=/run/secrets/db_password
      - DB_NAME=myapp
    depends_on:
      mysql:
        condition: service_healthy
    restart: unless-stopped

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
      MYSQL_DATABASE: myapp
      MYSQL_USER: app_user
      MYSQL_PASSWORD_FILE: /run/secrets/db_password
    volumes:
      - mysql_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  mysql_data:

উপসংহার

একটি শক্তিশালী Node.js এবং MySQL ব্যাকএন্ড তৈরি করার জন্য আর্কিটেকচার, নিরাপত্তা, কর্মক্ষমতা এবং অপারেশনাল উদ্বেগের দিকে মনোযোগ দেওয়া প্রয়োজন। একটি পরিষ্কার প্রকল্প কাঠামো প্রতিষ্ঠা করে, যথাযথ প্রমাণীকরণ এবং বৈধতা প্রয়োগ করে, ডাটাবেস কোয়েরি অপ্টিমাইজ করে এবং আপনার স্থাপনার কন্টেইনারাইজ করে, আপনি একটি ব্যাকএন্ড তৈরি করেন যা সুরক্ষিত, কার্যকরী এবং রক্ষণাবেক্ষণযোগ্য। এই নির্দেশিকায় বর্ণিত মৌলিক বিষয়গুলি দিয়ে শুরু করুন, বাস্তবসম্মত লোডের অধীনে আপনার অ্যাপ্লিকেশনের কার্যকারিতা পরিমাপ করুন এবং আপনি যে প্রতিবন্ধকতাগুলি আবিষ্কার করেছেন সেগুলি পুনরাবৃত্তি করুন৷ এখানে উপস্থাপিত নিদর্শন হাজার হাজার উত্পাদন অ্যাপ্লিকেশন জুড়ে প্রমাণিত হয়েছে এবং আপনার ব্যাকএন্ড সিস্টেমের জন্য একটি শক্ত ভিত্তি হিসাবে কাজ করবে।