Building Production-Ready Node.js Applications: Database Integration, Authentication, and API Management

1. MongoDB Fundamentals

Relational vs Non-Relational Databases

Relational databases rely on SQL for operations and maintain strict ACID (Atomicity, Consistency, Isolation, Durability) compliance through transaction mechanisms. Common examples include MySQL, SQL Server, DB2, and Oracle.

Non-relational databases, often referred to as "Not Only SQL," prioritize flexibility, lightweight architecture, and high efficiency. Examples include MongoDB, HBase, and Redis.

MongoDB is frequently chosen for its unique data handling: it can load hot data into memory for extremely fast read operations (though this consumes significant RAM). Using BSON for storage provides excellent support for JSON-like data structures and allows for flexible schema modifications. Its document-based storage is intuitive, and it offers robust horizontal scaling through sharding and reliable automatic failover.

SQL Concept MongoDB Concept Description
database database Database instance
table collection Database table / Collection
row document Data record / Document
column field Data field / Attribute
index index Index
table joins N/A Table joins are not supported in MongoDB
primary key primary key Primary key; MongoDB auto-sets the _id field

Installation

Download and install the community edition from the official MongoDB documentation.

Starting the Server

Windows:

mongod --dbpath d:/data/db
mongo

macOS:

mongod --config /usr/local/etc/mongod.conf
mongo

Command Line Operations

Database Management:

// Check help commands
help
db.help()

// Switch to or create a database named 'music'
use music

// List all databases
show dbs

// Check current database
db.getName()

// Display database status and version
db.stats()
db.version()

// Drop current database
db.dropDatabase()

Collection Management:

// Create a capped collection (max 5MB, 5000 docs)
db.createCollection("collName", {size: 5242880, capped: true, max: 5000});

// Get specific collection
db.getCollection("account");

// List all collections
db.getCollectionNames();

// Drop a collection
db.users.drop();

CRUD Operations:

// Create
db.users.save({name: "zhangsan", age: 25, sex: true});
db.users.insertMany([{name: "lisi", age: 30}, {name: "wangwu", age: 22}]);

// Update (equivalent to SQL: UPDATE users SET name="changeName" WHERE age=25)
db.users.update({age: 25}, {$set: {name: "changeName"}}, false, true);

// Delete
db.users.remove({age: 132});

// Read all
db.userInfo.find();

// Distinct values
db.userInfo.distinct("name");

// Comparison queries
db.userInfo.find({age: {$gt: 22}}); // age > 22
db.userInfo.find({age: {$gte: 23, $lte: 26}}); // age between 23 and 26

// Regex (Like %mongo%)
db.userInfo.find({name: /mongo/});

// Projection (Select specific fields)
db.userInfo.find({age: {$gt: 25}}, {name: 1, age: 1});

// Sorting and Pagination
db.userInfo.find().sort({age: -1}); // Descending
db.userInfo.find().skip(5).limit(5); // Skip 5, limit 5

// OR condition
db.userInfo.find({$or: [{age: 22}, {age: 25}]});

// Count
db.userInfo.find({age: {$gte: 25}}).count();

GUI Tools

Popular tools for managing MongoDB visually include Robo 3T (formerly Robomongo), and adminMongo.

Integrating with Node.js (Mongoose)

Connection:

const mongoose = require("mongoose");
mongoose.connect("mongodb://127.0.0.1:27017/company-system");

Schema Definition:

const mongoose = require("mongoose");
const { Schema } = mongoose;

const StaffSchemaDefinition = {
  username: String,
  password: String,
  gender: Number,
  introduction: String,
  avatar: String,
  role: Number
};

const StaffModel = mongoose.model("staff", new Schema(StaffSchemaDefinition));
module.exports = StaffModel;

Operations:

// Create
StaffModel.create({ introduction, username, gender, avatar, password, role });

// Read with pagination and sorting
StaffModel.find(
  { username: "kerwin" }, 
  ["username", "role", "introduction", "password"]
).sort({ createTime: -1 }).skip(10).limit(10);

// Update
StaffModel.updateOne({ _id }, { introduction, username, gender, avatar });

// Delete
StaffModel.deleteOne({ _id });

2. API Design and Architecutre

RESTful Conventions

RESTful architecture dictates that URLs should represent resources (nouns) while HTTP methods represent actions (verbs).

  • GET /api/staff - Retrieve list
  • POST /api/staff - Create new entry
  • PUT /api/staff/{id} - Update entry
  • DELETE /api/staff/{id} - Remove entry

Common filtering parameters:

  • ?limit=10: Limit results
  • ?page=2&per_page=100: Pagination
  • ?sortby=name&order=asc: Sorting

Business Logic Layering (MVC)

A standard Node.js application often separates concerns into layers:

  • Entry (index.js): Receives client requests.
  • Routing (router.js): Distributes requests to the Controller.
  • Controller (controller.js): Handles business logic and communicates between Model and View.
  • Model (model.js): Handles data logic (Database CRUD).
  • View (views): Presents the UI (HTML).

3. Authentication Strategies

Cookie & Session

HTTP is stateless. To maintain user sessions, the server generates a Session ID upon login, stores it (e.g., in MongoDB), and sends it to the browser via a Cookie. Subsequent requests from the browser include this Cookie, allowing the server to validate the session.

const express = require("express");
const session = require("express-session");
const MongoStore = require("connect-mongo");
const app = express();

app.use(session({
  secret: "complex_secret_key",
  resave: true,
  saveUninitialized: true,
  cookie: { maxAge: 1000 * 60 * 10 },
  rolling: true,
  store: MongoStore.create({
    mongoUrl: 'mongodb://127.0.0.1:27017/session_store',
    ttl: 1000 * 60 * 10
  }),
}));

// Auth Middleware
app.use((req, res, next) => {
  if (req.url === "/login") return next();
  if (req.session.user) {
    next();
  } else {
    res.redirect("/login");
  }
});

JSON Web Token (JWT)

JWT is a stateless authentication mechanism. Instead of storing session data on the server, the server generates a signed token containing user information (Payload) and sends it to the client. The client stores this token (usually in LocalStorage) and sends it in the Authorization header.

Implementation:

const jwt = require("jsonwebtoken");
const SECRET_KEY = "super_secret_123";

const AuthService = {
  issue(payload, duration) {
    return jwt.sign(payload, SECRET_KEY, { expiresIn: duration });
  },
  validate(token) {
    try {
      return jwt.verify(token, SECRET_KEY);
    } catch (error) {
      return null;
    }
  }
};
module.exports = AuthService;

Server-side Middleware:

app.use((req, res, next) => {
  if (req.url === "/login") return next();
  
  const authHeader = req.headers["authorization"];
  const token = authHeader && authHeader.split(" ")[1];
  
  if (token) {
    const decoded = AuthService.validate(token);
    if (decoded) {
      // Refresh token logic
      const refreshedToken = AuthService.issue({ id: decoded.id }, "1d");
      res.header("Authorization", refreshedToken);
      next();
    } else {
      res.status(401).json({ code: -1, msg: "Unauthorized" });
    }
  } else {
    res.status(401).json({ code: -1, msg: "Token missing" });
  }
});

Client-side Interceptor (Axios):

import axios from 'axios';

axios.interceptors.request.use(config => {
  const storedToken = localStorage.getItem("access_token");
  if (storedToken) config.headers.Authorization = `Bearer ${storedToken}`;
  return config;
});

axios.interceptors.response.use(response => {
  const newToken = response.headers['authorization'];
  if (newToken) localStorage.setItem("access_token", newToken);
  return response;
}, error => {
  if (error.response.status === 401) {
    localStorage.clear();
    window.location.href = "/login";
  }
  return Promise.reject(error);
});

4. File Upload Management

Use multer middleware to handle multipart/form-data for file uploads.

Server Setup:

const multer = require('multer');
const uploadMiddleware = multer({ dest: 'public/uploads/' });

router.post('/upload-asset', uploadMiddleware.single('fileResource'), (req, res) => {
  console.log(req.file); // Contains file metadata
  res.json({ path: `/uploads/${req.file.filename}` });
});

Client Request:

const formData = new FormData();
formData.append('fileResource', selectedFile);
formData.append('userId', '12345');

axios.post('/api/upload-asset', formData, {
  headers: { 'Content-Type': 'multipart/form-data' }
});

5. API Documentation with apidoc

apidoc generates documentation from inline code comments.

Install: npm install -g apidoc

Create apidoc.json in the root:

{
  "name": "Project API Docs",
  "version": "1.0.0",
  "description": "Documentation for backend services",
  "title": "API Reference"
}

Add comments in your route files:

/**
 * @api {get} /user/:id Get User Details
 * @apiName GetUserById
 * @apiGroup User
 *
 * @apiParam {Number} id Users unique ID.
 *
 * @apiSuccess {String} firstname User firstname.
 * @apiSuccess {String} lastname User lastname.
 */
app.get('/user/:id', (req, res) => { ... });

Generate docs: apidoc -i src/ -o docs/

Tags: Node.js mongodb mongoose REST API JWT

Posted on Mon, 20 Jul 2026 16:34:25 +0000 by inVINCEable