dynapm
v1.0.13
Published
DynaPM is a dynamic start-stop application management tool with serverless-like features designed for resource-constrained environments. It starts and stops programs on demand, optimizes resource usage, and is suitable for private deployments.
Readme
DynaPM
Dynamic Process Manager - A lightweight, universal service management system with serverless-like features.
DynaPM is a lightweight alternative to complex container orchestration platforms (like Knative, Sablier) for private deployments. It helps you manage hundreds of low-frequency services on resource-constrained servers by starting them on-demand and stopping them when idle.
🎯 Why DynaPM?
The Problem
You have many side projects or internal tools that:
- 🐌 Are accessed infrequently but need to be available instantly
- 💸 Consume valuable RAM/CPU even when idle
- 😓 Don't justify the complexity of Kubernetes/serverless platforms
- 🤔 Are managed differently (PM2, Docker, systemd, etc.)
💡 The Solution
DynaPM acts as a smart gateway that:
- Intercepts incoming requests to your services
- Automatically starts the service if offline (only 25ms overhead ⚡)
- Stream-proxies the request (1-2ms latency 🚀)
- Stops the service after a period of inactivity
💡 Performance Note: 25ms is DynaPM's overhead (startup command: 8ms + port wait: 17ms). Total cold start time also includes the service's own startup time (e.g., ~475ms for Node.js apps, ~500ms total).
🏆 What Makes DynaPM Different?
| Feature | DynaPM | Sablier | traefik-lazyload | Knative | |---------|--------|---------|------------------|---------| | Technology | Node.js + uWS | Go | Go | Go + K8s | | Scope | ⭐ Universal (any process) | Docker only | Docker only | K8s only | | Setup Complexity | ⭐ Simple | ⭐⭐⭐ Medium | ⭐⭐⭐ Medium | ⭐⭐⭐⭐⭐ Complex | | Infrastructure | Single server | Docker/K8s | Docker + Traefik | K8s cluster | | Cold Start | ⚡ ~25ms overhead | Container startup required | Container startup required | 2-4 seconds (source) | | Proxy Latency | 🚀 1-2ms | Via reverse proxy | Via reverse proxy | Via Activator/Queue-proxy | | Perfect For | Personal projects/Small teams | Docker environments | Docker + Traefic | Enterprise K8s |
✨ Key Features
⚡ Blazing Fast Cold Start
🚀 [myapp] GET / - Starting service...
[myapp] Start command executed
✅ [myapp] Service ready (startup: 8ms, wait: 17ms)
📤 [myapp] GET / - 200 - 30ms- DynaPM overhead: Only 25ms (startup command: 8ms + port wait: 17ms)
- Instant retry: Zero-delay polling, forward immediately when port is ready
- Total cold start: ~500ms (including service boot time, e.g., ~475ms for Node.js apps)
🚀 Stream Proxying
When services are running, proxy latency is only 1-2ms:
📤 [myapp] GET / - 200 - 1ms
📤 [myapp] POST /api/data - 200 - 2msTrue streaming with uWebSockets.js - zero buffering, 10x+ performance vs Fastify!
🌐 SSE & WebSocket Support
DynaPM supports modern real-time protocols out of the box:
Server-Sent Events (SSE):
✅ [sse-server] Service ready (startup: 3ms, wait: 429ms)
📤 [sse-server] GET /events - 200 - 5.45sWebSocket:
✅ [ws-server] Backend WebSocket connected
📨 [ws-server] Forward message to backend: 30 bytes
🔌 [ws-server] Client WebSocket closedSmart connection tracking prevents long connections from being shut down:
- Active SSE/WebSocket connections increment connection counter
- Services only stop when
activeConnections === 0AND timeout expires - No more premature service kills during active sessions
🎛️ Universal Service Management
Configure ANY service using bash commands - no limits:
// PM2 services
{
commands: {
start: 'pm2 start app.js --name myapp',
stop: 'pm2 stop myapp',
check: 'pm2 status | grep myapp | grep online',
}
}
// Docker containers
{
commands: {
start: 'docker run -d -p 3000:3000 myimage',
stop: 'docker stop mycontainer',
check: 'docker inspect -f {{.State.Running}} mycontainer',
}
}
// systemd services
{
commands: {
start: 'systemctl start myservice',
stop: 'systemctl stop myservice',
check: 'systemctl is-active myservice',
}
}
// Direct processes
{
commands: {
start: 'nohup node app.js > logs/app.log 2>&1 &',
stop: 'lsof -ti:3000 | xargs -r kill -9',
check: 'lsof -ti:3000 >/dev/null 2>&1',
}
}🔄 Idle Resource Reclamation
- Services auto-stop after X minutes of inactivity
- Configurable timeout per service
- Frees up RAM/CPU for active services
- Check interval: 3 seconds
- Smart connection tracking: Active long connections (SSE/WebSocket) prevent premature shutdown
📊 High Performance Metrics
Test Environment: Node.js HTTP Server (autocannon benchmark)
✅ Cold start: ~48ms (DynaPM: 25ms + service boot: 23ms)
✅ Stream proxy: Avg 9.5ms (range: 8-14ms)
✅ Throughput: 8,383 req/s (multi-service, 60 concurrent)
✅ Load test: Low latency even under high concurrency
✅ Memory overhead: ~50MB (Node.js runtime)
✅ Bundle size: 21.7KB (minified)
✅ Logging: Structured JSON logging (Pino)🚀 Quick Start
Installation
# Install globally
npm install -g dynapm
# Or use with pnpm
pnpm install -g dynapmConfiguration
Create a dynapm.config.ts file in your project directory:
import type { DynaPMConfig } from 'dynapm';
const config: DynaPMConfig = {
port: 3000,
host: '127.0.0.1',
// Logging configuration (optional, disable for better performance in production)
logging: {
enableRequestLog: false, // Enable request/response logging (high frequency, affects performance)
enableWebSocketLog: false, // Enable WebSocket lifecycle logging
// Error logging is always enabled
},
services: {
'app.example.com': {
name: 'my-app',
base: 'http://127.0.0.1:3001',
idleTimeout: 5 * 60 * 1000, // Auto-stop after 5 minutes idle
startTimeout: 10 * 1000, // Startup timeout
commands: {
start: 'nohup node /path/to/app.js > logs/app.log 2>&1 &',
stop: 'lsof -ti:3001 | xargs -r kill -9',
check: 'lsof -ti:3001 >/dev/null 2>&1',
},
healthCheck: {
type: 'tcp', // TCP port check (default, no service code changes needed)
},
},
},
};
export default config;Usage
# Start the DynaPM gateway
dynapm
# Or use with npx
npx dynapmNow access your services at http://app.example.com:3000 - they'll start automatically!
🧪 Running Tests
DynaPM comes with a comprehensive automated test suite covering all core features.
Quick Test
# Clone the project
git clone https://github.com/2234839/DynaPM.git
cd DynaPM
# Install dependencies
pnpm install
# Run the full test suite
pnpm testTest Coverage
The automated tests validate 12 core functionalities:
- ✅ On-demand start - Services auto-start when offline
- ✅ Hot start - Direct proxy when service is running
- ✅ Auto-stop - Services auto-stop after timeout
- ✅ 404 handling - Unconfigured services return 404
- ✅ Multi-service - Manage multiple services concurrently
- ✅ Health checks - TCP and HTTP check methods
- ✅ Path proxying - Different paths proxy correctly
- ✅ Idle protection - Continuous requests update idle time
- ✅ POST requests - POST method support
- ✅ SSE streaming - Server-Sent Events proxy support
- ✅ WebSocket - WebSocket bidirectional communication support
- ✅ Long connections - Active connections prevent premature shutdown
Test Output Example
============================================================
Test Results Summary
============================================================
✓ Test 1: On-demand start (773ms)
✓ Test 2: Hot start (service running) (11ms)
✓ Test 3: Auto-stop (18025ms)
✓ Test 4: 404 error handling (11ms)
✓ Test 5: Multi-service concurrent start (843ms)
✓ Test 6: Different health checks (20ms)
✓ Test 7: Path proxying (10ms)
✓ Test 8: Idle time update on continuous requests (14112ms)
✓ Test 9: POST requests (12ms)
✓ Test 10: SSE streaming (3963ms)
✓ Test 11: WebSocket (1098ms)
✓ Test 12: Long connections (10110ms)
------------------------------------------------------------
Total: 12 tests
Passed: 12 ✓
Failed: 0
🎉 All tests passed!Performance Verification
Tests output detailed performance logs:
🚀 [app1] GET / - Starting service...
[app1] Start command executed
✅ [app1] Service ready (startup: 8ms, wait: 17ms)
📤 [app1] GET / - 200 - 30ms
# Subsequent requests (service already running)
📤 [app1] GET / - 200 - 1ms
📤 [app1] POST /api/data - 200 - 2ms📊 Performance Benchmarking
DynaPM includes an automated performance test script to verify system metrics.
Running Performance Tests
# Clone the project
git clone https://github.com/2234839/DynaPM.git
cd DynaPM
# Install dependencies
pnpm install
# Build the project
pnpm build
# Run performance benchmark
pnpm benchmarkPerformance Test Output
🚀 DynaPM Performance Benchmark
============================================================
Cold Start Performance
============================================================
✓ Cold start success, total time: 48ms
DynaPM overhead: ~25ms (startup command + port wait)
Service boot: ~23ms (Node.js application)
============================================================
Stream Proxy Latency
============================================================
✓ Stream proxy test completed (10 requests)
Average latency: 9.5ms
Min latency: 8ms
Max latency: 14ms
Latency range: 8ms - 14ms
============================================================
Throughput Test (autocannon)
============================================================
ℹ Running 5s load test (50 concurrent)...
Multi-service throughput: 8,383 req/s
Single-service throughput: 4,225+ req/s
Average latency: ~23ms
Zero errors under high concurrencyTest Requirements
- Node.js: Run DynaPM gateway
- curl: Basic functionality testing
- autocannon (optional): Throughput load testing
Install autocannon:
npm install -g autocannon📖 Configuration Examples
Check out dynapm.config.example.ts for complete examples including:
- PM2-managed Node.js apps
- Docker containers
- systemd services
- Direct process management
- Environment variables
- Custom health checks (HTTP/TCP/Command)
🏗️ Architecture
┌─────────────────────────────────────────────────┐
│ User Request │
│ http://app.example.com:3000/api/data │
└──────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ DynaPM Gateway (uWebSockets.js) │
│ - Check service status (memory cached) │
│ - Execute start command if needed (8ms) │
│ - Fast TCP port polling (17ms, zero-delay retry)│
│ - Stream proxy request (1-2ms) │
│ - Structured logging (Pino, async) │
└──────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Your Services │
│ - PM2, Docker, systemd, or any process │
│ - Auto-stopped when idle │
└─────────────────────────────────────────────────┘Core Optimizations
- Memory state cache - No bash command execution on every request
- Fast TCP port check - 100ms timeout, instant retry on failure
- Stream forward instead of wait - Forward immediately when port is ready
- Startup time breakdown - Clear display of command time vs wait time
📊 Performance Benchmarks
All performance data measured via pnpm benchmark script.
Cold Start Performance
Test: Total time from offline to first accessible request
Results:
├─ DynaPM overhead: 25ms (startup command: 8ms + TCP port wait: 17ms)
├─ Service boot: 17ms (Node.js application)
└─ Total cold start: 42msStream Proxy Performance
Test: Single request latency when service is running
Results:
├─ Average latency: 9.3ms
├─ Min latency: 8ms
├─ Max latency: 12ms
└─ Latency range: 8-12msThroughput Performance
Test: Multi-service benchmark (3 services × 20 concurrent, 5 seconds)
Results:
├─ Total requests: 42,000 requests
├─ Average throughput: 8,383 req/s
├─ Per-service: 2,794 req/s
├─ Errors: 0
└─ Test duration: 5 seconds
Test: Single service benchmark (50 concurrent, 5 seconds)
Results:
├─ Requests/sec: 4,225+ req/s
├─ Average latency: ~23ms
└─ Total requests: 21k requestsResource Usage
Runtime resource usage:
├─ Memory: ~50MB (Node.js runtime)
├─ CPU: <1% when idle
├─ Disk: 21.7KB (bundle size, minified)
├─ Network: Proxy traffic only, no overhead
└─ Logging: Async structured logging (Pino)🎨 Use Cases
- 👨💻 Personal projects: Keep dozens of side projects ready without eating RAM
- 🛠️ Internal tools: On-demand access to development/testing environments
- 🔧 Microservices: Lightweight alternative to Kubernetes for small deployments
- 💰 Resource optimization: Maximize server utilization by stopping idle services
- 📦 Cost saving: Run more services on smaller VPS instances
- 🎓 Learning & experiments: Easily manage multiple test projects
🔧 Roadmap
- [ ] 🎛️ Web Dashboard - Service monitoring and management UI
- [ ] 📈 Prometheus Integration - Metrics collection and visualization
- [ ] 📋 Service Templates - One-click PM2/Docker config generation
- [ ] 🔄 Multi-instance Support - Distributed locking and state sync
- [ ] 🔌 Plugin System - Custom integrations and extensions
- [ ] 🌐 More Health Checks - gRPC, Redis, etc.
- [x] ⚡ uWebSockets.js Migration - Completed (10x+ performance improvement)
- [x] 📊 Structured Logging - Completed (Pino async logging)
📦 Publishing Releases
DynaPM uses GitHub Actions to automatically publish to npm, requiring no manual tokens or 2FA.
Release Process
The project uses npm OIDC (OpenID Connect) Trusted Publishing, automatically triggered by Git tags:
# Method 1: patch version (bug fixes)
npm version patch
git push origin main --tags
# Method 2: minor version (new features)
npm version minor
git push origin main --tags
# Method 3: major version (breaking changes)
npm version major
git push origin main --tagsAutomated Release Workflow
After pushing a tag, GitHub Actions automatically:
- ✅ Build project - Compile TypeScript with rslib
- ✅ Verify build - Check output file integrity
- ✅ Publish to npm - Use OIDC, no tokens needed
- ✅ Create Release - Generate release notes on GitHub
Monitor Release Status
- GitHub Actions: https://github.com/2234839/DynaPM/actions
- npm package: https://www.npmjs.com/package/dynapm
Verify Release
# Check latest version
npm view dynapm version
# View version history
npm view dynapm versions --json
# Install and test
npm install -g dynapm@latestPublishing Configuration
This project uses npm Trusted Publishing:
- ✅ No NPM_TOKEN environment variable needed
- ✅ No two-factor authentication (2FA) required
- ✅ Automatic verification via GitHub Actions OIDC
- ✅ More secure (short-lived tokens, auto-expiry)
For detailed setup: docs/NPM_OIDC_SETUP.md
Version Numbering
Follows Semantic Versioning:
- 1.0.4 → 1.0.5 (
patch): Bug fixes - 1.0.4 → 1.1.0 (
minor): New features, backward compatible - 1.0.4 → 2.0.0 (
major): Breaking changes
🤝 Contributing
Contributions are welcome! Feel free to open issues or submit pull requests.
Workflow:
- Fork the project
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
📄 License
ISC
🙏 Acknowledgments
Built with amazing open-source tools:
- uWebSockets.js - Highest performance web server for Node.js (10x+ faster than Fastify)
- Pino - Extreme fast structured logger
- c12 - Configuration loader
📮 Support
- 🐛 Bug Reports: GitHub Issues
- 💡 Feature Requests: GitHub Discussions
- 👤 Author: 崮生
⚡ Made with ❤️ for resource-conscious developers
