Pulse

Development: Started - Updated

Pulse is a distributed synthetic monitoring system for checking service reachability and behaviour from multiple locations. It separates the monitoring control plane from the agents that execute checks, so one dashboard can compare what different machines and networks observe.

The problem

A conventional uptime check answers a narrow question: can one monitoring location reach this service? That is useful, but it does not explain whether the service behaves the same way from another network, a different machine, or a different operating system.

Pulse was built to ask the broader question. Agents run the same definition where they are installed, then report response time and failure details to a shared control plane. A result that fails from one network but not another becomes visible without moving the check definition or assembling logs by hand.

Architecture

Pulse Server sends check definitions to agents over HTTP; agents return results from their separate networks.

The solution has four parts:

Why this design

Why agents? A check must run where the observation matters. Installing a worker on Windows or Linux lets Pulse compare the same service from separate networks instead of inferring every failure from the server's location.

Why pull configuration over HTTP? Agents periodically request their definitions and push completed results back. That keeps the connection model simple for machines behind ordinary outbound-only network rules and lets an agent converge after a configuration change without a server-initiated connection.

Why HTTP rather than WebSockets? The system exchanges bounded requests: definitions on a heartbeat and batched results after checks finish. A persistent bidirectional channel would add connection management without improving that flow.

Why centralise configuration? Checks are defined once in the control plane. Each agent receives the same target, interval, timeout, and type, which makes cross-agent comparisons meaningful.

Why SQLite? The first deployment has one small, local data store with no separate database service. It fits a focused monitoring tool; it is not presented as a multi-node database strategy.

Why Blazor and shared contracts? Blazor keeps the operational UI in the same .NET stack, while Pulse.Contracts prevents the server, worker, and dashboard from independently redefining their request and result shapes.

Monitoring behaviour

Agents run HTTP, ping, and TCP checks. HTTP considers a 2xx response healthy and falls back from HEAD to GET when a target rejects HEAD. Every check carries its own interval and timeout; failures preserve the elapsed time and error detail instead of disappearing into a boolean status.

An agent heartbeats by pulling definitions. The server records when it was last seen, and the radar treats an agent as online only when that heartbeat is no more than five minutes old. The scheduler starts newly assigned checks, stops removed ones, and restarts a loop when its target, type, interval, or timeout changes.

Result submission is buffered in batches of up to 50 or five seconds. If a batch cannot be sent, the agent puts its results back on the in-memory channel and retries after a short delay. Registration also retries with increasing delays, while the worker keeps its main heartbeat loop alive after ordinary errors.

The dashboard has views for agents, checks, and results. Its radar compares recent outcomes across agents, including availability, response time, errors, and the last heartbeat. That makes a distinction visible: a target can be healthy overall while still failing from one particular place.

What I would improve next

Pulse is intentionally small, so its production limits are clear. I would replace the single SQLite deployment with a managed relational database and add retention or rollups for old results before the result table becomes a long-term time-series store.

I would also make result delivery durable across an agent restart, bound the retry queue, and add explicit alerting, authentication rotation, and high-availability control-plane deployment. Those changes solve observed operational ceilings; they are not necessary to demonstrate the current control-plane-and-agent model.

View the source on GitHub