Prerequisites
- Basic understanding of JavaScript ๐
- TypeScript installation โก
- VS Code or preferred IDE ๐ป
- Node.js fundamentals ๐ฅ๏ธ
What you'll learn
- Understand PM2 process management fundamentals ๐ฏ
- Apply PM2 in real TypeScript projects ๐๏ธ
- Debug common PM2 integration issues ๐
- Write type-safe process management code โจ
๐ฏ Introduction
Welcome to this exciting tutorial on PM2 process management! ๐ In this guide, weโll explore how to supercharge your TypeScript Node.js applications with PM2โs powerful process management capabilities.
Youโll discover how PM2 can transform your TypeScript backend development experience. Whether youโre building web servers ๐, microservices ๐ฅ๏ธ, or API gateways ๐, understanding PM2 is essential for creating production-ready, scalable applications.
By the end of this tutorial, youโll feel confident deploying and managing TypeScript applications with PM2! Letโs dive in! ๐โโ๏ธ
๐ Understanding PM2
๐ค What is PM2?
PM2 is like a superhero manager for your Node.js applications ๐ฆธโโ๏ธ. Think of it as a personal assistant that keeps your apps running smoothly, restarts them if they crash, and helps them scale to handle more users!
In TypeScript terms, PM2 is a production process manager that provides:
- โจ Zero-downtime deployments
- ๐ Automatic application restarts
- ๐ก๏ธ Built-in load balancing and clustering
- ๐ Real-time monitoring and logging
- ๐ Hot reloading for development
๐ก Why Use PM2 with TypeScript?
Hereโs why developers love PM2 for TypeScript projects:
- Production Ready ๐ญ: Handle crashes gracefully
- Performance โก: Built-in clustering for multi-core utilization
- Developer Experience ๐ป: Hot reload during development
- Monitoring ๐: Real-time app metrics and logs
- DevOps Integration ๐ง: Easy CI/CD pipeline integration
Real-world example: Imagine building an e-commerce API ๐. With PM2, if your checkout service crashes during Black Friday traffic, PM2 automatically restarts it in milliseconds - your customers never notice!
๐ง Basic Setup and Usage
๐ฆ Installation
Letโs start with installing PM2 globally:
# ๐ Install PM2 globally
npm install -g pm2
# ๐ Verify installation
pm2 --version
๐ Simple TypeScript App
First, letโs create a TypeScript application to manage:
// ๐ app.ts - Our sample TypeScript server
import express from 'express';
const app = express();
const PORT = process.env.PORT || 3000;
// ๐จ Middleware
app.use(express.json());
// ๐ Routes
app.get('/', (req, res) => {
res.json({
message: 'Hello from TypeScript! ๐',
timestamp: new Date().toISOString(),
process: process.pid
});
});
app.get('/health', (req, res) => {
res.json({
status: 'healthy ๐',
uptime: process.uptime(),
memory: process.memoryUsage()
});
});
// ๐ฏ Start server
app.listen(PORT, () => {
console.log(`๐ Server running on port ${PORT} with PID ${process.pid}`);
});
export default app;
๐ฏ Package.json Setup
{
"name": "typescript-pm2-app",
"scripts": {
"build": "tsc",
"start": "node dist/app.js",
"dev": "ts-node app.ts",
"pm2:start": "pm2 start ecosystem.config.js",
"pm2:stop": "pm2 stop all",
"pm2:restart": "pm2 restart all",
"pm2:logs": "pm2 logs"
},
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"@types/express": "^4.17.0",
"@types/node": "^18.0.0",
"typescript": "^4.9.0",
"ts-node": "^10.9.0"
}
}
๐ก Practical Examples
๐ Example 1: E-commerce API with PM2
Letโs build a production-ready e-commerce API:
// ๐๏ธ ecommerce-api.ts
import express from 'express';
import { createServer } from 'http';
interface Product {
id: string;
name: string;
price: number;
emoji: string;
stock: number;
}
interface Order {
id: string;
products: Product[];
total: number;
status: 'pending' | 'processing' | 'shipped' | 'delivered';
emoji: string;
}
class EcommerceAPI {
private app = express();
private server = createServer(this.app);
private products: Product[] = [];
private orders: Order[] = [];
constructor() {
this.setupMiddleware();
this.setupRoutes();
this.seedData();
}
// ๐ง Setup middleware
private setupMiddleware(): void {
this.app.use(express.json());
// ๐ Request logging
this.app.use((req, res, next) => {
console.log(`๐ ${new Date().toISOString()} - ${req.method} ${req.path} - PID: ${process.pid}`);
next();
});
}
// ๐ Setup routes
private setupRoutes(): void {
// ๐ Health check
this.app.get('/health', (req, res) => {
res.json({
status: 'healthy ๐',
process: process.pid,
uptime: process.uptime(),
memory: process.memoryUsage()
});
});
// ๐ฆ Get products
this.app.get('/products', (req, res) => {
res.json({
success: true,
products: this.products,
message: 'Products fetched successfully! ๐๏ธ'
});
});
// ๐ Create order
this.app.post('/orders', (req, res) => {
const { productIds } = req.body;
try {
const orderProducts = this.products.filter(p =>
productIds.includes(p.id) && p.stock > 0
);
if (orderProducts.length === 0) {
return res.status(400).json({
success: false,
message: 'No available products found! ๐
'
});
}
const order: Order = {
id: `order_${Date.now()}`,
products: orderProducts,
total: orderProducts.reduce((sum, p) => sum + p.price, 0),
status: 'pending',
emoji: '๐ฆ'
};
this.orders.push(order);
// ๐ Update stock
orderProducts.forEach(orderedProduct => {
const product = this.products.find(p => p.id === orderedProduct.id);
if (product) product.stock--;
});
res.json({
success: true,
order,
message: 'Order created successfully! ๐'
});
} catch (error) {
console.error('โ Order creation failed:', error);
res.status(500).json({
success: false,
message: 'Failed to create order ๐ฐ'
});
}
});
// ๐ Get orders
this.app.get('/orders', (req, res) => {
res.json({
success: true,
orders: this.orders,
message: 'Orders fetched successfully! ๐ฆ'
});
});
}
// ๐ฑ Seed initial data
private seedData(): void {
this.products = [
{ id: '1', name: 'TypeScript Handbook', price: 29.99, emoji: '๐', stock: 10 },
{ id: '2', name: 'Premium Coffee', price: 12.99, emoji: 'โ', stock: 50 },
{ id: '3', name: 'Wireless Headphones', price: 89.99, emoji: '๐ง', stock: 5 },
{ id: '4', name: 'Laptop Sticker Pack', price: 4.99, emoji: '๐ป', stock: 100 }
];
}
// ๐ Start server
start(port: number = 3000): void {
this.server.listen(port, () => {
console.log(`๐ E-commerce API running on port ${port}`);
console.log(`๐ Process ID: ${process.pid}`);
console.log(`โก Environment: ${process.env.NODE_ENV || 'development'}`);
});
}
// ๐ Graceful shutdown
shutdown(): void {
console.log('๐ Shutting down gracefully...');
this.server.close(() => {
console.log('โ
Server closed successfully');
process.exit(0);
});
}
}
// ๐ฏ Handle graceful shutdown
const api = new EcommerceAPI();
process.on('SIGTERM', () => api.shutdown());
process.on('SIGINT', () => api.shutdown());
// ๐ Start the API
api.start(parseInt(process.env.PORT || '3000'));
๐ฎ Example 2: PM2 Ecosystem Configuration
Create a comprehensive PM2 configuration:
// ๐ง ecosystem.config.js
module.exports = {
apps: [
{
// ๐๏ธ E-commerce API
name: 'ecommerce-api',
script: './dist/ecommerce-api.js',
instances: 'max', // ๐ Use all CPU cores
exec_mode: 'cluster',
env: {
NODE_ENV: 'development',
PORT: 3000
},
env_production: {
NODE_ENV: 'production',
PORT: 8080
},
// ๐ Monitoring options
log_file: './logs/combined.log',
out_file: './logs/out.log',
error_file: './logs/error.log',
time: true,
// ๐ Restart options
watch: false,
ignore_watch: ['node_modules', 'logs'],
max_memory_restart: '1G',
// ๐ก๏ธ Advanced options
kill_timeout: 5000,
wait_ready: true,
listen_timeout: 10000
},
{
// ๐ฏ Background worker
name: 'order-processor',
script: './dist/worker.js',
instances: 2,
exec_mode: 'cluster',
cron_restart: '0 0 * * *', // ๐ Restart daily at midnight
env: {
NODE_ENV: 'development',
WORKER_TYPE: 'order-processor'
},
env_production: {
NODE_ENV: 'production',
WORKER_TYPE: 'order-processor'
}
}
],
// ๐ Deploy configuration
deploy: {
production: {
user: 'deploy',
host: 'your-server.com',
ref: 'origin/main',
repo: '[email protected]:your-username/your-repo.git',
path: '/var/www/your-app',
'post-deploy': 'npm install && npm run build && pm2 reload ecosystem.config.js --env production'
}
}
};
๐ Example 3: TypeScript Process Monitor
// ๐ process-monitor.ts
import pm2 from 'pm2';
interface ProcessInfo {
name: string;
pid: number;
status: string;
cpu: number;
memory: number;
uptime: number;
emoji: string;
}
class PM2Monitor {
private processes: ProcessInfo[] = [];
// ๐ Connect to PM2
async connect(): Promise<void> {
return new Promise((resolve, reject) => {
pm2.connect((err) => {
if (err) {
console.error('โ Failed to connect to PM2:', err);
reject(err);
} else {
console.log('โ
Connected to PM2 successfully! ๐');
resolve();
}
});
});
}
// ๐ Get process list
async getProcessList(): Promise<ProcessInfo[]> {
return new Promise((resolve, reject) => {
pm2.list((err, list) => {
if (err) {
reject(err);
return;
}
this.processes = list.map(proc => ({
name: proc.name || 'unknown',
pid: proc.pid || 0,
status: proc.pm2_env?.status || 'unknown',
cpu: proc.cpu || 0,
memory: (proc.memory || 0) / 1024 / 1024, // ๐ Convert to MB
uptime: Date.now() - (proc.pm2_env?.created_at || 0),
emoji: this.getStatusEmoji(proc.pm2_env?.status || 'unknown')
}));
resolve(this.processes);
});
});
}
// ๐จ Get status emoji
private getStatusEmoji(status: string): string {
const emojiMap: Record<string, string> = {
'online': '๐ข',
'stopped': '๐ด',
'stopping': '๐ก',
'launching': '๐ก',
'errored': '๐ฅ',
'one-launch-status': '๐ต'
};
return emojiMap[status] || 'โช';
}
// ๐ Display process stats
displayStats(): void {
console.log('\n๐ PM2 Process Monitor Dashboard');
console.log('================================');
if (this.processes.length === 0) {
console.log('๐ด No processes running');
return;
}
this.processes.forEach(proc => {
console.log(`${proc.emoji} ${proc.name}`);
console.log(` PID: ${proc.pid}`);
console.log(` Status: ${proc.status}`);
console.log(` CPU: ${proc.cpu.toFixed(1)}%`);
console.log(` Memory: ${proc.memory.toFixed(1)} MB`);
console.log(` Uptime: ${this.formatUptime(proc.uptime)}`);
console.log('');
});
}
// โฐ Format uptime
private formatUptime(ms: number): string {
const seconds = Math.floor(ms / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
if (hours > 0) return `${hours}h ${minutes % 60}m`;
if (minutes > 0) return `${minutes}m ${seconds % 60}s`;
return `${seconds}s`;
}
// ๐ Start monitoring
async startMonitoring(interval: number = 5000): Promise<void> {
console.log('๐ Starting PM2 monitoring...');
setInterval(async () => {
try {
await this.getProcessList();
console.clear();
this.displayStats();
} catch (error) {
console.error('โ Monitoring error:', error);
}
}, interval);
}
// ๐ Disconnect
disconnect(): void {
pm2.disconnect();
console.log('๐ Disconnected from PM2');
}
}
// ๐ฏ Usage example
async function runMonitor() {
const monitor = new PM2Monitor();
try {
await monitor.connect();
await monitor.startMonitoring();
} catch (error) {
console.error('๐ฅ Monitor failed:', error);
monitor.disconnect();
}
}
// ๐ Start monitoring if this file is run directly
if (require.main === module) {
runMonitor();
}
export default PM2Monitor;
๐ Advanced Concepts
๐งโโ๏ธ Advanced Configuration Patterns
When youโre ready to level up, try these advanced PM2 patterns:
// ๐ฏ Advanced ecosystem configuration with TypeScript types
interface PM2AppConfig {
name: string;
script: string;
instances: number | 'max';
exec_mode: 'cluster' | 'fork';
env: Record<string, string>;
env_production: Record<string, string>;
log_file: string;
out_file: string;
error_file: string;
time: boolean;
max_memory_restart: string;
kill_timeout: number;
wait_ready: boolean;
listen_timeout: number;
}
interface PM2EcosystemConfig {
apps: PM2AppConfig[];
deploy?: {
production: {
user: string;
host: string;
ref: string;
repo: string;
path: string;
'post-deploy': string;
};
};
}
// ๐ช Type-safe ecosystem configuration
const createEcosystemConfig = (): PM2EcosystemConfig => ({
apps: [
{
name: 'typescript-api',
script: './dist/app.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'development',
PORT: '3000',
LOG_LEVEL: 'debug'
},
env_production: {
NODE_ENV: 'production',
PORT: '8080',
LOG_LEVEL: 'info'
},
log_file: './logs/combined.log',
out_file: './logs/out.log',
error_file: './logs/error.log',
time: true,
max_memory_restart: '1G',
kill_timeout: 5000,
wait_ready: true,
listen_timeout: 10000
}
]
});
๐๏ธ Advanced Health Monitoring
For the brave developers, hereโs a comprehensive health monitoring system:
// ๐ Advanced health monitoring with PM2
interface HealthMetrics {
timestamp: Date;
process: {
pid: number;
uptime: number;
memory: NodeJS.MemoryUsage;
cpu: number;
};
application: {
status: 'healthy' | 'degraded' | 'unhealthy';
responseTime: number;
errorRate: number;
throughput: number;
};
emoji: string;
}
class AdvancedHealthMonitor {
private metrics: HealthMetrics[] = [];
private readonly maxMetrics = 100; // ๐ Keep last 100 measurements
// ๐ Collect comprehensive metrics
async collectMetrics(): Promise<HealthMetrics> {
const startTime = Date.now();
// ๐งช Simulate application health check
const healthCheck = await this.performHealthCheck();
const responseTime = Date.now() - startTime;
const metrics: HealthMetrics = {
timestamp: new Date(),
process: {
pid: process.pid,
uptime: process.uptime(),
memory: process.memoryUsage(),
cpu: process.cpuUsage().user / 1000000 // ๐ Convert to percentage
},
application: {
status: healthCheck.status,
responseTime,
errorRate: this.calculateErrorRate(),
throughput: this.calculateThroughput()
},
emoji: this.getHealthEmoji(healthCheck.status)
};
this.addMetrics(metrics);
return metrics;
}
// ๐ฉบ Perform application health check
private async performHealthCheck(): Promise<{ status: 'healthy' | 'degraded' | 'unhealthy' }> {
try {
// ๐งช Add your health checks here
const checks = [
this.checkDatabase(),
this.checkExternalServices(),
this.checkMemoryUsage()
];
const results = await Promise.all(checks);
const failedChecks = results.filter(r => !r).length;
if (failedChecks === 0) return { status: 'healthy' };
if (failedChecks <= 1) return { status: 'degraded' };
return { status: 'unhealthy' };
} catch (error) {
console.error('โ Health check failed:', error);
return { status: 'unhealthy' };
}
}
// ๐๏ธ Mock health checks
private async checkDatabase(): Promise<boolean> {
// ๐งช Simulate database check
return new Promise(resolve => setTimeout(() => resolve(Math.random() > 0.1), 50));
}
private async checkExternalServices(): Promise<boolean> {
// ๐ Simulate external service check
return new Promise(resolve => setTimeout(() => resolve(Math.random() > 0.05), 100));
}
private async checkMemoryUsage(): Promise<boolean> {
const usage = process.memoryUsage();
const usedMB = usage.heapUsed / 1024 / 1024;
return usedMB < 512; // ๐ Fail if using more than 512MB
}
// ๐ Calculate error rate
private calculateErrorRate(): number {
// ๐งฎ Mock calculation - in real app, track actual errors
return Math.random() * 5; // 0-5% error rate
}
// ๐ Calculate throughput
private calculateThroughput(): number {
// ๐ Mock calculation - in real app, track actual requests
return Math.floor(Math.random() * 1000); // 0-1000 requests/min
}
// ๐จ Get health emoji
private getHealthEmoji(status: string): string {
const emojiMap: Record<string, string> = {
'healthy': '๐',
'degraded': '๐ก',
'unhealthy': '๐ด'
};
return emojiMap[status] || 'โช';
}
// ๐ Add metrics to collection
private addMetrics(metrics: HealthMetrics): void {
this.metrics.push(metrics);
if (this.metrics.length > this.maxMetrics) {
this.metrics.shift(); // ๐๏ธ Remove oldest metric
}
}
// ๐ Get health summary
getHealthSummary(): string {
if (this.metrics.length === 0) return '๐ด No metrics available';
const latest = this.metrics[this.metrics.length - 1];
const memoryMB = (latest.process.memory.heapUsed / 1024 / 1024).toFixed(1);
return `
๐ Health Summary (PID: ${latest.process.pid})
${latest.emoji} Status: ${latest.application.status}
โก Response Time: ${latest.application.responseTime}ms
๐ง Memory: ${memoryMB}MB
๐ Throughput: ${latest.application.throughput} req/min
โ Error Rate: ${latest.application.errorRate.toFixed(2)}%
โฑ๏ธ Uptime: ${Math.floor(latest.process.uptime / 60)}m
`.trim();
}
}
โ ๏ธ Common Pitfalls and Solutions
๐ฑ Pitfall 1: Memory Leaks in Cluster Mode
// โ Wrong way - no cleanup!
class LeakyServer {
private intervals: NodeJS.Timeout[] = [];
start() {
// ๐ฅ This will create memory leaks in cluster mode!
this.intervals.push(setInterval(() => {
console.log('Still running...');
}, 1000));
}
}
// โ
Correct way - proper cleanup!
class CleanServer {
private intervals: NodeJS.Timeout[] = [];
start() {
const interval = setInterval(() => {
console.log('โ
Running cleanly...');
}, 1000);
this.intervals.push(interval);
}
// ๐งน Cleanup method
cleanup() {
console.log('๐งน Cleaning up intervals...');
this.intervals.forEach(interval => clearInterval(interval));
this.intervals = [];
}
// ๐ Graceful shutdown
setupGracefulShutdown() {
process.on('SIGTERM', () => {
console.log('๐ Received SIGTERM, shutting down gracefully');
this.cleanup();
process.exit(0);
});
}
}
๐คฏ Pitfall 2: Ignoring PM2 Signals
// โ Dangerous - ignoring PM2 lifecycle!
const server = express();
server.listen(3000, () => {
console.log('Server started');
// ๐ฅ No signal handling - PM2 can't manage this properly!
});
// โ
Safe - proper PM2 integration!
const server = express();
const httpServer = server.listen(3000, () => {
console.log('โ
Server started with PM2 integration');
// ๐ก Tell PM2 we're ready
if (process.send) {
process.send('ready');
}
});
// ๐ก๏ธ Handle PM2 signals properly
process.on('SIGINT', () => {
console.log('๐ Received SIGINT, shutting down...');
httpServer.close(() => {
console.log('โ
HTTP server closed');
process.exit(0);
});
});
๐ ๏ธ Best Practices
- ๐ฏ Use Ecosystem Files: Always configure PM2 with ecosystem.config.js
- ๐ Enable Logging: Set up proper log rotation and monitoring
- ๐ก๏ธ Graceful Shutdowns: Handle SIGTERM and SIGINT signals properly
- ๐ Cluster Mode: Use cluster mode for CPU-intensive applications
- ๐ Monitor Resources: Set memory limits and restart thresholds
- โก Health Checks: Implement comprehensive health monitoring
- ๐ Zero Downtime: Use
pm2 reload
for deployments - ๐ฆ Environment Management: Use different configs for dev/prod
๐งช Hands-On Exercise
๐ฏ Challenge: Build a Complete PM2-Managed Microservice
Create a TypeScript microservice with full PM2 integration:
๐ Requirements:
- โ Express API with health checks
- ๐ท๏ธ PM2 ecosystem configuration
- ๐ค Process monitoring dashboard
- ๐ Graceful shutdown handling
- ๐จ Real-time metrics collection
- ๐ Error handling and logging
๐ Bonus Points:
- Add clustering with load balancing
- Implement automatic scaling based on CPU usage
- Create a deployment script with zero downtime
- Add integration with monitoring tools
๐ก Solution
๐ Click to see solution
// ๐ฏ Complete microservice with PM2 integration
import express from 'express';
import { createServer } from 'http';
interface ServiceMetrics {
requests: number;
errors: number;
uptime: number;
memory: number;
}
class MicroService {
private app = express();
private server = createServer(this.app);
private metrics: ServiceMetrics = {
requests: 0,
errors: 0,
uptime: Date.now(),
memory: 0
};
constructor() {
this.setupMiddleware();
this.setupRoutes();
this.setupGracefulShutdown();
}
// ๐ง Setup middleware
private setupMiddleware(): void {
this.app.use(express.json());
// ๐ Request counter
this.app.use((req, res, next) => {
this.metrics.requests++;
console.log(`๐ ${new Date().toISOString()} - ${req.method} ${req.path} - PID: ${process.pid}`);
next();
});
// โ Error counter
this.app.use((error: any, req: any, res: any, next: any) => {
this.metrics.errors++;
console.error('โ Error:', error);
res.status(500).json({ error: 'Internal server error' });
});
}
// ๐ Setup routes
private setupRoutes(): void {
// ๐ Health check
this.app.get('/health', (req, res) => {
const memUsage = process.memoryUsage();
this.metrics.memory = memUsage.heapUsed / 1024 / 1024;
res.json({
status: 'healthy ๐',
process: process.pid,
uptime: (Date.now() - this.metrics.uptime) / 1000,
memory: `${this.metrics.memory.toFixed(2)} MB`,
metrics: this.metrics
});
});
// ๐ Metrics endpoint
this.app.get('/metrics', (req, res) => {
res.json({
...this.metrics,
timestamp: new Date().toISOString(),
process: {
pid: process.pid,
version: process.version,
platform: process.platform
}
});
});
// ๐ฎ Demo endpoints
this.app.get('/api/users', (req, res) => {
res.json([
{ id: 1, name: 'Alice ๐ฉโ๐ป', role: 'developer' },
{ id: 2, name: 'Bob ๐จโ๐ง', role: 'devops' }
]);
});
this.app.post('/api/simulate-error', (req, res) => {
throw new Error('๐ฅ Simulated error for testing!');
});
}
// ๐ Graceful shutdown
private setupGracefulShutdown(): void {
const shutdown = (signal: string) => {
console.log(`๐ Received ${signal}, shutting down gracefully...`);
this.server.close(() => {
console.log('โ
HTTP server closed');
console.log('๐ Final metrics:', this.metrics);
process.exit(0);
});
// ๐ Force shutdown after 10 seconds
setTimeout(() => {
console.log('โ ๏ธ Force shutdown after timeout');
process.exit(1);
}, 10000);
};
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));
}
// ๐ Start server
start(port: number = 3000): void {
this.server.listen(port, () => {
console.log(`๐ Microservice running on port ${port}`);
console.log(`๐ Process ID: ${process.pid}`);
console.log(`โก Environment: ${process.env.NODE_ENV || 'development'}`);
// ๐ก Tell PM2 we're ready
if (process.send) {
process.send('ready');
}
});
}
}
// ๐ฏ Start the microservice
const service = new MicroService();
service.start(parseInt(process.env.PORT || '3000'));
Ecosystem Configuration:
// ๐ง ecosystem.config.js
module.exports = {
apps: [{
name: 'typescript-microservice',
script: './dist/microservice.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'development',
PORT: 3000
},
env_production: {
NODE_ENV: 'production',
PORT: 8080
},
log_file: './logs/combined.log',
out_file: './logs/out.log',
error_file: './logs/error.log',
time: true,
max_memory_restart: '500M',
kill_timeout: 5000,
wait_ready: true,
listen_timeout: 10000,
restart_delay: 1000
}]
};
Package.json Scripts:
{
"scripts": {
"build": "tsc",
"start": "pm2 start ecosystem.config.js",
"dev": "pm2 start ecosystem.config.js --env development --watch",
"stop": "pm2 stop typescript-microservice",
"restart": "pm2 restart typescript-microservice",
"logs": "pm2 logs typescript-microservice",
"monitor": "pm2 monit",
"reload": "pm2 reload typescript-microservice",
"delete": "pm2 delete typescript-microservice"
}
}
๐ Key Takeaways
Youโve learned so much! Hereโs what you can now do:
- โ Set up PM2 with TypeScript applications confidently ๐ช
- โ Configure ecosystem files for production deployments ๐ก๏ธ
- โ Implement health monitoring and metrics collection ๐ฏ
- โ Handle graceful shutdowns and process signals ๐
- โ Build production-ready Node.js services! ๐
Remember: PM2 is your production companion, not your enemy! Itโs here to help you build reliable, scalable applications. ๐ค
๐ค Next Steps
Congratulations! ๐ Youโve mastered PM2 integration with TypeScript!
Hereโs what to do next:
- ๐ป Practice with the microservice exercise above
- ๐๏ธ Add PM2 to your existing TypeScript projects
- ๐ Move on to our next tutorial: Docker Integration with TypeScript
- ๐ Share your PM2 deployment successes with others!
Remember: Every TypeScript expert was once a beginner. Keep coding, keep deploying, and most importantly, have fun! ๐
Happy coding! ๐๐โจ