Microservices Architecture
Master microservices architecture principles, design patterns, and implementation strategies for building scalable Node.js applications.
90 minā¢By Priygop Teamā¢Last updated: Feb 2026
Microservices Fundamentals
Microservices architecture is an approach to building applications as a collection of loosely coupled, independently deployable services that communicate over well-defined APIs.
Microservices vs Monolith
Example
// Monolithic architecture example
const express = require('express');
const app = express();
// All services in one application
app.use('/users', userRoutes);
app.use('/orders', orderRoutes);
app.use('/payments', paymentRoutes);
app.use('/inventory', inventoryRoutes);
app.listen(3000, () => {
console.log('Monolithic app running on port 3000');
});
// Microservices architecture
// user-service/index.js
const express = require('express');
const app = express();
app.use('/users', userRoutes);
app.listen(3001, () => {
console.log('User service running on port 3001');
});
// order-service/index.js
const express = require('express');
const app = express();
app.use('/orders', orderRoutes);
app.listen(3002, () => {
console.log('Order service running on port 3002');
});Service Design Principles
- Single Responsibility: Each service should have one business capability
- Autonomous: Services should be independently deployable
- Decentralized: No single point of failure
- Fault Tolerant: Services should handle failures gracefully
- Observable: Services should be monitorable and debuggable
- API-First: Design APIs before implementation
Domain-Driven Design
Example
// Domain-driven design for microservices
// user-service/domain/User.js
class User {
constructor(id, email, name) {
this.id = id;
this.email = email;
this.name = name;
this.createdAt = new Date();
}
validate() {
if (!this.email || !this.email.includes('@')) {
throw new Error('Invalid email');
}
if (!this.name || this.name.length < 2) {
throw new Error('Invalid name');
}
}
toJSON() {
return {
id: this.id,
email: this.email,
name: this.name,
createdAt: this.createdAt
};
}
}
// user-service/repository/UserRepository.js
class UserRepository {
constructor(database) {
this.db = database;
}
async findById(id) {
const user = await this.db.users.findById(id);
return user ? new User(user.id, user.email, user.name) : null;
}
async save(user) {
user.validate();
return await this.db.users.create(user.toJSON());
}
}Service Communication Patterns
Example
// Synchronous communication with HTTP
const axios = require('axios');
class UserService {
constructor() {
this.baseURL = process.env.USER_SERVICE_URL || 'http://user-service:3001';
}
async getUser(id) {
try {
const response = await axios.get(`${this.baseURL}/users/${id}`);
return response.data;
} catch (error) {
if (error.response?.status === 404) {
return null;
}
throw new Error('Failed to fetch user');
}
}
}
// Asynchronous communication with message queues
const amqp = require('amqplib');
class OrderService {
constructor() {
this.connection = null;
this.channel = null;
}
async connect() {
this.connection = await amqp.connect(process.env.RABBITMQ_URL);
this.channel = await this.connection.createChannel();
// Declare queues
await this.channel.assertQueue('order.created', { durable: true });
await this.channel.assertQueue('order.updated', { durable: true });
}
async publishOrderCreated(order) {
await this.channel.sendToQueue(
'order.created',
Buffer.from(JSON.stringify(order)),
{ persistent: true }
);
}
}Mini-Project: E-commerce Microservices
Example
// Complete microservices implementation
// api-gateway/index.js
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const rateLimit = require('express-rate-limit');
const app = express();
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.use(limiter);
app.use(express.json());
// Service discovery and routing
const services = {
user: process.env.USER_SERVICE_URL || 'http://user-service:3001',
product: process.env.PRODUCT_SERVICE_URL || 'http://product-service:3002',
order: process.env.ORDER_SERVICE_URL || 'http://order-service:3003',
payment: process.env.PAYMENT_SERVICE_URL || 'http://payment-service:3004'
};
// Proxy middleware for each service
Object.entries(services).forEach(([service, target]) => {
app.use(`/${service}`, createProxyMiddleware({
target,
changeOrigin: true,
pathRewrite: {
[`^/${service}`]: ''
},
onError: (err, req, res) => {
res.status(503).json({
error: 'Service unavailable',
service,
message: err.message
});
}
}));
});
// Health check endpoint
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
services: Object.keys(services)
});
});
app.listen(3000, () => {
console.log('API Gateway running on port 3000');
});
// user-service/index.js
const express = require('express');
const mongoose = require('mongoose');
const User = require('./models/User');
const app = express();
app.use(express.json());
// Database connection
mongoose.connect(process.env.MONGODB_URL || 'mongodb://localhost:27017/users');
// Routes
app.get('/users/:id', async (req, res) => {
try {
const user = await User.findById(req.params.id);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
res.json(user);
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
app.post('/users', async (req, res) => {
try {
const user = new User(req.body);
await user.save();
res.status(201).json(user);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
app.listen(3001, () => {
console.log('User service running on port 3001');
});