A minimal Dead Man’s Switch API built with Express and in-memory storage.
Pulse-Check-API tracks monitor heartbeats and marks targets as DOWN when a timeout expires. It uses a single Express app, a simple service layer, and per-monitor setTimeout timers to keep the lifecycle easy to reason about.
server.js: application entrypoint and middleware setup.routes/monitors.js: REST endpoints for monitor operations.services/monitorService.js: core monitor lifecycle, validation, and timer management.data/store.js: in-memory storage for monitor records and timer handles.config/swagger.js: API documentation served at/api-docs.
- keep domain logic in the service layer
- avoid persistent storage complexity
- use one active timer per monitor
- do not use cron jobs, queues, or external caches
- Install dependencies:
npm install
- Start the server:
npm start
- Open API docs at:
http://localhost:3000/api-docs
POST /monitors
Request body:
{
"id": "device-123",
"timeout": 60000,
"alert_email": "admin@critmon.com",
"name": "Solar Farm A"
}Success response:
{
"message": "Monitor created",
"monitor": {
"id": "device-123",
"name": "Solar Farm A",
"alert_email": "admin@critmon.com",
"timeout": 60000,
"status": "ACTIVE",
"lastHeartbeat": 1680000000000,
"createdAt": 1680000000000,
"updatedAt": 1680000000000
}
}POST /monitors/:id/heartbeat
Behavior:
- existing
ACTIVEmonitor resets the timeout and updateslastHeartbeat PAUSEDmonitor is automatically unpaused and restarted- if monitor does not exist, returns
404 - current implementation also recovers
DOWNmonitors toACTIVE
Success response:
{
"message": "Heartbeat received",
"monitor": {
"id": "device-123",
"status": "ACTIVE",
"lastHeartbeat": 1680000060000,
"updatedAt": 1680000060000
}
}POST /monitors/:id/pause
Behavior:
- sets
statustoPAUSED - clears the active timeout
- prevents timeout alerts while paused
POST /monitors/:id/resume
Behavior:
- sets
statustoACTIVE - restarts the timeout from the current time
GET /monitors
GET /monitors/:id
Returns the monitor object or 404 if the monitor does not exist.
Monitors move through three states:
ACTIVE: timer is running and heartbeat is expectedPAUSED: timer is stopped and no alert will fireDOWN: timeout expired and an alert was logged
Transitions:
ACTIVE→PAUSEDvia/pausePAUSED→ACTIVEvia/heartbeator/resumeACTIVE→DOWNwhen the timer expiresDOWN→ACTIVEwhen/heartbeatis received (current recovery choice)
Note: in this implementation, a heartbeat after
DOWNautomatically recovers the monitor toACTIVE. This is the chosen behavior for the prototype and is documented here.
- add request validation middleware instead of inline checks
- return proper
404for missing monitor detail requests - persist monitors in a database for production state durability
- add DELETE support to remove monitors and clear timers
- add integration tests for timer expiration and pause/resume transitions