Summary
Node.js is a JavaScript runtime built on Chrome's V8 engine that enables server-side JavaScript development. This cheatsheet covers core Node.js concepts including the event loop, asynchronous programming patterns, module systems, file system operations, HTTP servers, Express.js framework, database integration, authentication, security best practices, error handling, performance optimization, testing strategies, and common design patterns. Key features include non-blocking I/O, single-threaded event loop, NPM ecosystem, and scalability through clustering and microservices architecture.
1. Node.js Fundamentals
What is Node.js?
- JavaScript runtime built on Chrome's V8 engine
- Event-driven, non-blocking I/O model
- Single-threaded but highly scalable
Global Objects
console.log(__dirname); // Current directory path
console.log(__filename); // Current file path
console.log(process.env); // Environment variables
console.log(process.argv); // Command line arguments
Process Object
process.exit(0); // Exit with success
process.exit(1); // Exit with error
process.on('uncaughtException', (err) => {
console.error('Uncaught Exception:', err);
});
2. Module System
CommonJS (Traditional)
// math.js
exports.add = (a, b) => a + b;
module.exports = { multiply: (a, b) => a * b };
// main.js
const math = require('./math');
const { add } = require('./math');
ES Modules (Modern)
// math.mjs
export const add = (a, b) => a + b;
export default function multiply(a, b) { return a * b; }
// main.mjs
import multiply, { add } from './math.mjs';
3. Event Loop & Async Patterns
Event Loop Phases
- Timers: setTimeout, setInterval
- Pending Callbacks: I/O callbacks
- Idle, Prepare: Internal use
- Poll: Retrieve new I/O events
- Check: setImmediate callbacks
- Close Callbacks: socket.on('close')
Callbacks
fs.readFile('file.txt', (err, data) => {
if (err) return console.error(err);
console.log(data);
});
Promises
const readFile = (path) => {
return new Promise((resolve, reject) => {
fs.readFile(path, (err, data) => {
if (err) reject(err);
else resolve(data);
});
});
};
Async/Await
async function readFiles() {
try {
const data1 = await fs.promises.readFile('file1.txt');
const data2 = await fs.promises.readFile('file2.txt');
return [data1, data2];
} catch (error) {
console.error(error);
}
}
Event Emitter
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (data) => {
console.log('Event triggered:', data);
});
myEmitter.emit('event', 'Hello World');
4. File System Operations
Reading Files
// Synchronous
const data = fs.readFileSync('file.txt', 'utf8');
// Asynchronous
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// Promise-based
const data = await fs.promises.readFile('file.txt', 'utf8');
Writing Files
// Write (overwrite)
fs.writeFileSync('file.txt', 'Hello World');
// Append
fs.appendFileSync('file.txt', '\nNew Line');
// Stream for large files
const writeStream = fs.createWriteStream('large.txt');
writeStream.write('chunk of data');
writeStream.end();
5. HTTP/HTTPS Server
Basic HTTP Server
const http = require('http');
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ message: 'Hello World' }));
});
server.listen(3000, () => {
console.log('Server running on port 3000');
});
HTTPS Server
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('private-key.pem'),
cert: fs.readFileSync('certificate.pem')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('Secure Hello World');
}).listen(443);
6. Express.js Essentials
Basic Setup
const express = require('express');
const app = express();
// Middleware
app.use(express.json()); // Parse JSON bodies
app.use(express.urlencoded({ extended: true })); // Parse URL-encoded bodies
// Routes
app.get('/', (req, res) => {
res.json({ message: 'Hello World' });
});
app.post('/users', (req, res) => {
const { name, email } = req.body;
res.status(201).json({ id: 1, name, email });
});
app.listen(3000);
Middleware
// Custom middleware
const logger = (req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
};
app.use(logger);
// Error handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
Router
const router = express.Router();
router.get('/users', (req, res) => {
res.json({ users: [] });
});
router.get('/users/:id', (req, res) => {
const { id } = req.params;
res.json({ id, name: 'John' });
});
app.use('/api', router);
7. Database Integration
MongoDB with Mongoose
const mongoose = require('mongoose');
// Connection
mongoose.connect('mongodb://localhost/myapp', {
useNewUrlParser: true,
useUnifiedTopology: true
});
// Schema & Model
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, unique: true },
age: Number
});
const User = mongoose.model('User', userSchema);
// CRUD Operations
const user = await User.create({ name: 'John', email: 'john@example.com' });
const users = await User.find({ age: { $gte: 18 } });
await User.updateOne({ _id: id }, { name: 'Jane' });
await User.deleteOne({ _id: id });
PostgreSQL with pg
const { Pool } = require('pg');
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});
// Query
const result = await pool.query('SELECT * FROM users WHERE id = $1', [userId]);
// Transaction
const client = await pool.connect();
try {
await client.query('BEGIN');
await client.query('INSERT INTO users(name) VALUES($1)', ['John']);
await client.query('COMMIT');
} catch (e) {
await client.query('ROLLBACK');
throw e;
} finally {
client.release();
}
8. Authentication & Security
JWT Authentication
const jwt = require('jsonwebtoken');
// Generate token
const token = jwt.sign(
{ userId: user.id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
// Verify token middleware
const authMiddleware = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (error) {
res.status(403).json({ error: 'Invalid token' });
}
};
Password Hashing with bcrypt
const bcrypt = require('bcrypt');
// Hash password
const saltRounds = 10;
const hashedPassword = await bcrypt.hash(plainPassword, saltRounds);
// Verify password
const isValid = await bcrypt.compare(plainPassword, hashedPassword);
Security Best Practices
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
// Security headers
app.use(helmet());
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.use('/api/', limiter);
// CORS
const cors = require('cors');
app.use(cors({
origin: 'https://trusted-domain.com',
credentials: true
}));
9. Error Handling
Try-Catch with Async/Await
const asyncHandler = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
app.get('/users', asyncHandler(async (req, res) => {
const users = await User.find();
res.json(users);
}));
Custom Error Class
class AppError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
this.isOperational = true;
Error.captureStackTrace(this, this.constructor);
}
}
// Usage
throw new AppError('User not found', 404);
10. Testing
Unit Testing with Jest
// math.test.js
const { add, multiply } = require('./math');
describe('Math functions', () => {
test('adds 1 + 2 to equal 3', () => {
expect(add(1, 2)).toBe(3);
});
test('multiplies 3 * 4 to equal 12', () => {
expect(multiply(3, 4)).toBe(12);
});
});
API Testing with Supertest
const request = require('supertest');
const app = require('./app');
describe('GET /api/users', () => {
it('responds with json', async () => {
const response = await request(app)
.get('/api/users')
.expect('Content-Type', /json/)
.expect(200);
expect(response.body).toHaveProperty('users');
});
});
11. Performance Optimization
Clustering
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker) => {
console.log(`Worker ${worker.process.pid} died`);
cluster.fork();
});
} else {
require('./app');
}
Caching with Redis
const redis = require('redis');
const client = redis.createClient();
// Cache middleware
const cache = (req, res, next) => {
const { id } = req.params;
client.get(id, (err, data) => {
if (err) throw err;
if (data !== null) {
res.json(JSON.parse(data));
} else {
next();
}
});
};
// Set cache
client.setex(id, 3600, JSON.stringify(data));
Stream Processing
// Process large files efficiently
const readStream = fs.createReadStream('large-file.txt');
const writeStream = fs.createWriteStream('output.txt');
readStream
.pipe(transform) // Transform stream
.pipe(writeStream)
.on('finish', () => console.log('Processing complete'));
12. Common Interview Patterns
Singleton Pattern
class Database {
constructor() {
if (Database.instance) {
return Database.instance;
}
this.connection = null;
Database.instance = this;
}
connect() {
this.connection = 'Connected';
return this.connection;
}
}
const db1 = new Database();
const db2 = new Database();
console.log(db1 === db2); // true
Factory Pattern
class UserFactory {
static createUser(type) {
switch(type) {
case 'admin':
return new AdminUser();
case 'regular':
return new RegularUser();
default:
throw new Error('Invalid user type');
}
}
}
Middleware Pattern
const pipeline = (...middlewares) => {
return (req, res) => {
const execute = (index) => {
if (index >= middlewares.length) return;
middlewares[index](req, res, () => execute(index + 1));
};
execute(0);
};
};
13. Key Concepts & Comparisons
Node.js Event Loop Phases Deep Dive
| Phase | Purpose | Executes | Next Phase Condition |
|---|---|---|---|
| Timer | Execute setTimeout/setInterval callbacks | Timer callbacks | All expired timers processed |
| Pending Callbacks | Execute I/O callbacks deferred to next loop | I/O error callbacks | All pending callbacks processed |
| Idle, Prepare | Internal Node.js operations | Internal use only | Automatic |
| Poll | Fetch new I/O events | New I/O callbacks | Poll queue empty or limit reached |
| Check | Execute setImmediate callbacks | setImmediate callbacks | All setImmediate processed |
| Close Callbacks | Execute close event callbacks | socket.on('close') | All close callbacks processed |
Callback vs Promise vs Async/Await
| Pattern | Syntax | Error Handling | Readability | Use Case |
|---|---|---|---|---|
| Callback | func(callback) |
Error-first callback | Poor (callback hell) | Legacy APIs, simple operations |
| Promise | .then().catch() |
.catch() chain |
Better | Modern async operations |
| Async/Await | async/await |
try/catch |
Best | Complex async workflows |
// Callback Hell
getData((err, data) => {
if (err) throw err;
processData(data, (err, result) => {
if (err) throw err;
saveResult(result, (err) => {
if (err) throw err;
console.log('Done');
});
});
});
// Promise Chain
getData()
.then(data => processData(data))
.then(result => saveResult(result))
.then(() => console.log('Done'))
.catch(err => console.error(err));
// Async/Await
async function workflow() {
try {
const data = await getData();
const result = await processData(data);
await saveResult(result);
console.log('Done');
} catch (err) {
console.error(err);
}
}
Module Systems Comparison
| System | Syntax | Loading | Use Case | Browser Support |
|---|---|---|---|---|
| CommonJS | require/module.exports |
Synchronous | Node.js applications | No (requires bundler) |
| ES Modules | import/export |
Asynchronous | Modern applications | Yes (modern browsers) |
| AMD | define/require |
Asynchronous | Browser applications | Yes (with RequireJS) |
| UMD | Universal format | Both | Libraries | Yes |
Stream Types & Use Cases
| Stream Type | Purpose | Example | When to Use |
|---|---|---|---|
| Readable | Read data source | fs.createReadStream() |
File reading, HTTP requests |
| Writable | Write data destination | fs.createWriteStream() |
File writing, HTTP responses |
| Duplex | Both readable and writable | net.Socket |
Network connections |
| Transform | Modify data as it passes | zlib.createGzip() |
Data transformation |
Memory Management Patterns
| Issue | Cause | Prevention | Detection |
|---|---|---|---|
| Global Variables | Unintentional globals | Use strict mode, proper scoping | Memory profiling |
| Closures | Retained references | Clear references when done | Heap snapshots |
| Event Listeners | Uncleaned listeners | Remove listeners on cleanup | Event listener audit |
| Timers | Forgotten intervals/timeouts | Clear timers explicitly | Timer tracking |
| Circular References | Objects referencing each other | Weak references, manual cleanup | Reference analysis |
Express.js Middleware Order & Types
| Type | Order | Purpose | Example |
|---|---|---|---|
| Application-level | 1 | Global middleware | app.use(express.json()) |
| Router-level | 2 | Route-specific middleware | router.use('/users', auth) |
| Error-handling | Last | Handle errors | app.use((err, req, res, next) => {}) |
| Built-in | Varies | Express functionality | express.static() |
| Third-party | Varies | External functionality | helmet(), cors() |
Database Integration Patterns
| Database | Driver/ORM | Connection Pattern | Use Case |
|---|---|---|---|
| MongoDB | Mongoose | Connection pooling | Document-based applications |
| PostgreSQL | pg, Sequelize | Connection pooling | Relational applications |
| Redis | redis | Connection management | Caching, sessions |
| MySQL | mysql2, Sequelize | Connection pooling | Traditional web applications |
Authentication Strategies Comparison
| Strategy | Security Level | Scalability | State | Use Case |
|---|---|---|---|---|
| Session-based | Medium | Limited | Stateful | Traditional web apps |
| JWT | High | High | Stateless | APIs, SPAs |
| OAuth 2.0 | High | High | Varies | Third-party integration |
| API Keys | Medium | High | Stateless | Service-to-service |
Error Handling Strategies
| Pattern | Implementation | Pros | Cons | Use Case |
|---|---|---|---|---|
| Try-Catch | try/catch blocks |
Simple, local control | Doesn't catch async errors | Sync operations |
| Promise Catch | .catch() method |
Handles promise rejections | Chain complexity | Promise-based code |
| Error Middleware | Express error handler | Centralized handling | Global scope | Express applications |
| Domain | Domain module | Process isolation | Deprecated | Legacy applications |
| Process Events | process.on('uncaughtException') |
Last resort handling | Application termination | Critical error logging |
Performance Optimization Techniques
| Technique | Implementation | Impact | Trade-offs |
|---|---|---|---|
| Clustering | cluster module |
CPU utilization | Memory overhead |
| Worker Threads | worker_threads |
CPU-intensive tasks | Complexity |
| Caching | Redis, in-memory | Response time | Memory usage |
| Connection Pooling | Database pools | Database performance | Resource management |
| Compression | compression middleware |
Bandwidth usage | CPU overhead |
| Load Balancing | Reverse proxy | Scalability | Infrastructure complexity |
Testing Pyramid for Node.js
| Test Type | Scope | Speed | Cost | Tools |
|---|---|---|---|---|
| Unit Tests | Individual functions/modules | Fast | Low | Jest, Mocha |
| Integration Tests | Module interactions | Medium | Medium | Supertest, Chai |
| E2E Tests | Full application flow | Slow | High | Cypress, Puppeteer |
| Contract Tests | API contracts | Medium | Medium | Pact |
Security Vulnerabilities & Mitigation
| Vulnerability | Description | Prevention | Tools |
|---|---|---|---|
| Injection | SQL/NoSQL/Command injection | Parameterized queries, validation | ESLint security rules |
| Broken Authentication | Weak auth implementation | Strong passwords, MFA | bcrypt, speakeasy |
| Sensitive Data Exposure | Unencrypted data | Encryption, HTTPS | helmet, crypto |
| XXE | XML External Entity attacks | Disable external entities | libxml security settings |
| Broken Access Control | Improper authorization | Role-based access | JWT, RBAC |
| Security Misconfiguration | Default/weak configurations | Security headers, updates | helmet, audit tools |
| XSS | Cross-site scripting | Input sanitization | DOMPurify, CSP |
| Insecure Deserialization | Untrusted data deserialization | Validation, signed tokens | JSON schema validation |
| Known Vulnerabilities | Outdated dependencies | Regular updates | npm audit, Snyk |
| Insufficient Logging | Poor monitoring | Comprehensive logging | Winston, Morgan |
Scalability Patterns
| Pattern | Implementation | Benefits | Considerations |
|---|---|---|---|
| Horizontal Scaling | Multiple instances | Better fault tolerance | Session management |
| Vertical Scaling | Increase resources | Simple implementation | Hardware limits |
| Microservices | Service decomposition | Independent deployment | Network complexity |
| Load Balancing | Distribute requests | Better resource utilization | Single point of failure |
| Caching | Store frequent data | Reduced database load | Cache invalidation |
| Database Sharding | Partition data | Scale database reads/writes | Query complexity |
Common Design Patterns in Node.js
| Pattern | Purpose | Implementation | Use Case |
|---|---|---|---|
| Singleton | Single instance | Module caching | Database connections |
| Factory | Object creation | Factory functions | User type creation |
| Observer | Event notification | EventEmitter | Real-time updates |
| Middleware | Request processing | Function chains | Express pipeline |
| Proxy | Control access | Proxy objects | API rate limiting |
| Adapter | Interface compatibility | Wrapper functions | Third-party integration |
Environment & Configuration Management
| Approach | Implementation | Pros | Cons |
|---|---|---|---|
| Environment Variables | process.env |
Secure, flexible | No type checking |
| Config Files | JSON/YAML files | Structured, version controlled | Can be committed accidentally |
| Config Libraries | dotenv, config |
Feature-rich | Additional dependency |
| External Config | Consul, etcd | Centralized, dynamic | Network dependency |
14. Best Practices Checklist
✅ Always handle errors (try-catch, error middleware)
✅ Use environment variables for configuration
✅ Implement proper logging (Winston, Morgan)
✅ Add input validation (Joi, express-validator)
✅ Use prepared statements to prevent SQL injection
✅ Implement rate limiting for APIs
✅ Add health check endpoints
✅ Use compression middleware for responses
✅ Enable CORS properly
✅ Keep dependencies updated
✅ Use process managers (PM2) in production
✅ Monitor memory usage and performance
15. Quick Command Reference
# NPM Commands
npm init -y # Initialize package.json
npm install express # Install dependency
npm install -D nodemon # Install dev dependency
npm audit # Check vulnerabilities
npm update # Update packages
# Process Management
node app.js # Run application
nodemon app.js # Auto-restart on changes
pm2 start app.js # Production process manager
pm2 logs # View logs
pm2 monit # Monitor resources
# Debugging
node --inspect app.js # Enable Chrome DevTools debugging
console.time('label') # Performance timing
console.timeEnd('label')
Quick Reference Commands
NPM Package Management
# Project initialization
npm init -y # Initialize package.json
npm install # Install all dependencies
npm install --production # Install only production dependencies
# Package installation
npm install express # Install and save to dependencies
npm install -D nodemon # Install as dev dependency
npm install -g @nestjs/cli # Install globally
# Package management
npm list # List installed packages
npm outdated # Check for outdated packages
npm update # Update packages
npm audit # Security audit
npm audit fix # Fix security issues
Process Management
# Development
node app.js # Run application
nodemon app.js # Auto-restart on changes
npm start # Run start script
npm run dev # Run development script
# Production (PM2)
pm2 start app.js # Start with PM2
pm2 start app.js --instances 4 # Start with clustering
pm2 list # List running processes
pm2 logs # View logs
pm2 monit # Monitor resources
pm2 restart app # Restart application
pm2 stop app # Stop application
pm2 delete app # Delete application
Debugging & Monitoring
# Debugging
node --inspect app.js # Enable Chrome DevTools debugging
node --inspect-brk app.js # Debug from start
node --prof app.js # Enable profiling
# Environment
NODE_ENV=production node app.js # Set environment
DEBUG=* node app.js # Enable debug output
Essential Node.js Patterns Summary
1. Event Loop & Async Patterns
- Master the event loop phases and async programming patterns
- Understand callbacks, promises, and async/await differences
- Know when to use each pattern and their trade-offs
2. Module System & Architecture
- CommonJS vs ES Modules comparison and usage
- Module patterns and best practices
- Package.json configuration and dependency management
3. HTTP/Express.js Fundamentals
- HTTP server creation and middleware patterns
- Express.js routing, middleware, and error handling
- Request/response handling and RESTful API design
4. Database Integration
- MongoDB with Mongoose for document databases
- PostgreSQL/MySQL with connection pooling
- Transaction management and query optimization
5. Security & Authentication
- JWT authentication and authorization patterns
- Input validation and sanitization
- Security headers and CORS configuration
6. Error Handling & Testing
- Comprehensive error handling strategies
- Unit testing with Jest, integration testing
- Error monitoring and logging best practices
7. Performance & Scalability
- Clustering and worker threads for CPU utilization
- Caching strategies with Redis
- Memory management and garbage collection
8. Production Deployment
- Environment configuration and secrets management
- Process managers (PM2) and container deployment
- Monitoring, logging, and health checks
Interview Pro Tips:
- Explain the Event Loop - Critical for Node.js understanding, know all 6 phases
- Know Async Patterns - Demonstrate callback hell → promises → async/await evolution
- Understand Streams - Essential for handling large data and memory efficiency
- Security First - Always mention security considerations (validation, headers, auth)
- Scalability Patterns - Clustering, load balancing, caching, microservices
- Testing Strategy - Unit, integration, and E2E testing with proper mocking
- Performance Optimization - Memory management, connection pooling, caching
- Error Handling - Comprehensive error handling and monitoring strategies