Distributed cron jobs for Node.js with Redis coordination
CronSync ensures your scheduled jobs run exactly once across multiple server instances. Perfect for microservices, Kubernetes deployments, and any distributed Node.js application.
npm install cronsync
const CronSync = require('cronsync');
const cronSync = new CronSync({
redisUrl: 'redis://localhost:6379'
});
// This job runs exactly once across all your instances
cronSync.schedule('0 2 * * *', 'daily-backup', async () => {
console.log('Running daily backup...');
// Your backup logic here
});
npm start
# Server runs on http://localhost:5500
# Schedule a job
cronsync schedule --name "backup" --cron "0 2 * * *" --script "scripts/backup.js"
# List all jobs
cronsync list
# Stop a job
cronsync stop --id "job-id-here"
# View job stats
cronsync stats --name "backup"
Without CronSync:
- Deploy your app to 3 servers
- Your daily backup job runs 3 times
- Data corruption and wasted resources
With CronSync:
- Same 3 servers
- Daily backup runs exactly once
- Redis coordinates which server executes
# Clone the repository
git clone https://github.com/mocklock-org/cronsync.git
cd cronsync
# Install dependencies
npm install
# Start Redis (required)
docker run -d -p 6379:6379 redis:alpine
# Start the server
npm run dev
# Using docker-compose
docker-compose up -d
# Or build and run manually
docker build -t cronsync .
docker run -p 3000:3000 -e REDIS_URL=redis://your-redis:6379 cronsync
POST /jobs
{
"name": "backup",
"cronPattern": "0 2 * * *",
"script": "scripts/backup.js"
}
GET /jobs
DELETE /jobs/:jobId
GET /jobs/:jobName/stats
PORT=3000 # API server port
REDIS_URL=redis://localhost:6379 # Redis connection
LOG_LEVEL=info # Logging level
const cronSync = new CronSync({
redisUrl: 'redis://localhost:6379',
instanceId: 'custom-instance-id', // Auto-generated if not provided
lockTimeout: 300000, // Lock timeout in ms (5 min default)
logLevel: 'info' // winston log level
});
CronSync provides built-in monitoring:
- Execution logs: All job runs are logged with timestamps and duration
- Job statistics: Success/failure rates, last run times
- Distributed coordination: Track which instance executed each job
- Error handling: Automatic lock release on failures
- Job Trigger: Cron pattern triggers on all instances
- Lock Attempt: Each instance tries to acquire Redis lock
- Winner Executes: Only one instance gets the lock and runs the job
- Automatic Cleanup: Lock is released after job completion or timeout
- Database backups across multiple app instances
- Report generation in distributed systems
- Cache warming for load-balanced applications
- Cleanup tasks in microservice architectures
- Batch processing in cloud deployments
const cronSync = new CronSync({
redisUrl: 'redis://primary:6379,redis://secondary:6379'
});
apiVersion: apps/v1
kind: Deployment
metadata:
name: cronsync
spec:
replicas: 3 # Multiple instances, jobs still run once
template:
spec:
containers:
- name: cronsync
image: your-registry/cronsync:latest
env:
- name: REDIS_URL
value: "redis://redis-service:6379"
- Minimal overhead: Only Redis calls added to job execution
- Fast coordination: Lock acquisition typically < 1ms
- Scalable: Tested with 100+ concurrent instances
- Reliable: Automatic failover if instance dies during job execution
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
MIT License - see LICENSE file for details
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: Wiki
CronSync - Because your scheduled jobs should run once, not once per server.