# express-status-monitor: a dashboard that can break the app it monitors

> A self-hosted realtime metrics module for Express servers, assembled from a websocket library and a charting library with templating underneath. Its documentation is unusually candid about the one default that will interfere with an existing project.

**RafalWilinski/express-status-monitor** — GitHub describes it as 🚀 Realtime Monitoring solution for Node.js/Express.js apps, inspired by status.github.com, sponsored by https://dynobase.dev. The repository metadata lists JavaScript as its primary language. The metadata lists the MIT license. This article stays within the project description and details documented in the GitHub repository README.

- Repository: https://github.com/RafalWilinski/express-status-monitor
- Website: https://dynobase.dev/
- Stars: 3,615 · Forks: 264
- Language: JavaScript
- License: MIT
- Published: 2026-08-13 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/rafalwilinski-express-status-monitor

## Two lines and a route

The installation is a dependency install and a single line of middleware.

```bash
npm install express-status-monitor --save
```

Plus the instruction that matters: the line has to go before any other middleware or router in the application. That ordering is not cosmetic. The module answers for a route, and anything registered earlier can claim the request first, which produces a page that never loads and no error to explain it. Once mounted, the dashboard is at a status route. The documentation also names the runtime floor in prose, saying the plugin works on newer major versions of the runtime than the fourth. There is an examples directory with its own dependency file and its own start script, and running it gives you the dashboard on a local port without wiring anything into your own application, which is the fastest way to see whether the charts suit you before you commit.

## The default samples at three rates and forgets after sixty points

The options object is passed into the constructor, and the defaults are worth reading rather than copying. Sampling is expressed as a list of spans, each with an interval and a retention count, and the defaults are one second, five seconds, and fifteen seconds, each keeping sixty data points in memory. That is a deliberate shape: a fast span for the last minute, a slower span for the last five, and the slowest for the last quarter of an hour. Anything beyond that window is gone, so this is a live view rather than a history you can query later. A title and a stylesheet name are configurable, as is the route the page is served from and the path the websocket listens on. Which charts appear is a separate map, covering processor, memory, load, event loop, heap, response time, requests per second, and status codes, so you can present the dashboard as a wall display or strip it back to three charts.

## Health checks are endpoints that must answer 200

You can add your own checks to the configuration, and they appear below the statistics rather than inside them. Each entry is a protocol, a host, a port, and a path, and the definition of success is deliberately blunt: the endpoint has to return a status code of 200.

```javascript
healthChecks: [{
  protocol: 'http',
  host: 'localhost',
  path: '/admin/health/ex1',
  port: '3000'
}]
```

There is no retry, no timeout, and no threshold in the visible configuration, which makes this feature a reachability indicator rather than a monitoring system. That is a reasonable trade for a page mounted on the same host, and it is why the examples use administrative paths on the same port: the point is to answer at a glance whether the things your service depends on are answering.

## The page handler is exposed so you can guard it yourself

The security section is the most useful part of the documentation, and its mechanism is simple: the middleware object exposes the page handler as a property, so you can mount the middleware for everything and then serve the page yourself behind whatever authentication you already use. Two examples are given, one using a login-requiring middleware and one using basic authentication. The second example contains the trick worth remembering, because it involves an odd configuration value: setting the path option to an empty string, with a comment explaining that this stops the middleware from serving the page itself, since the value has to be a string and must differ from the route you want. The example then mounts the middleware-only property so the websockets still work, and attaches the page handler behind the basic-auth check. Without that step the dashboard is public, which on a server with internal endpoints is not a small thing.

## It may start a second websocket server inside your process

There is one documented behaviour that can break an application rather than merely annoy it. If your project already uses websockets, the module warns that it could break your project, because by default it spawns its own websocket instance. The default therefore means a second server inside the same process, and two servers competing for the same path is exactly the kind of conflict that produces intermittent failures. The fix is described in one sentence: pass your existing websocket instance into the configuration, and set the port as well. The existence of that option, and the warning attached to the default, tells you something about the shape of the module, since a library whose happy path can break its host is one you wire up deliberately rather than try and forget.

## The runtime floor is stated twice and the two disagree

The documentation says the plugin works on runtime versions newer than the fourth, while the package manifest declares a minimum of the eighth. That is a small conflict, but it is the kind that produces a confusing installation failure, because one of the two statements will be what you read first. The release history is a larger version of the same problem. The tagged releases stop in 2017, while the manifest carries a version number that has never been tagged, and the branch itself was pushed to in early 2026. In other words, work continued after the last release without a new one, so the tags tell you nothing about what you would install today. The homepage in the manifest points at a company site rather than a documentation site, which is another small sign of where this project ended up.

## A sibling module exists for each other framework

The project is not trying to be framework-agnostic. Instead it names a separate module for each of two other web frameworks, one for a middleware-based architecture and one for a different style, both maintained by other people. That is a healthier arrangement than one package with adapters, because each module can follow its framework's own conventions, and it tells you the intended path if you are not using the target framework: adopt the sibling rather than forcing this one. The repository layout matches the era. A continuous integration configuration sits at the root under the filename convention the first generation of hosted build services used. The examples directory contains a small script whose name suggests it generates load, which is the right way to make a dashboard interesting. The dependency list explains the design: a templating engine for the page, a process-usage reader for processor and memory numbers, a header hook for response times, a websocket library, an HTTP client, and a debug logger.

## Conclusion

This module fits an Express service that needs a status page for its own operators, reachable on the same origin and configurable enough to show what you care about. Two things to check before you install it. If the project already uses websockets, read the warning section, because the default configuration starts a second server instance and the fix is a parameter you must remember to pass. And decide where the page is served from, because by default the middleware answers for that route and you have to move the handler behind your own login to lock it down.

## FAQ

### What is express-status-monitor used for?

It is a self-hosted module that shows realtime server metrics for an Express application, drawing charts in the browser over a websocket connection and holding the sampled values in memory. Which charts appear, how often they are sampled, and how many points are kept are all configurable.

### How do I install express-status-monitor?

Install it with the package manager, then add one line of middleware before any other middleware or router in the application, and visit the status route in a browser. The examples directory in the repository has its own dependency file and start script if you want to see the dashboard first.

### How do I protect the express-status-monitor page?

The middleware exposes the page handler as a property, so you mount the middleware for everything and then serve that handler yourself behind your own login or basic authentication. One documented trick is to set the configured path to an empty string so the middleware does not serve the page itself, then mount the middleware-only property so websockets keep working.

### Will express-status-monitor conflict with my existing websockets?

It can. The documentation warns that the module may break a project that already uses websockets, because by default it spawns its own websocket instance. The fix is to pass your existing instance into the configuration along with the port.

## Sources

- [Official documentation](https://dynobase.dev/)
- [Official README](https://github.com/RafalWilinski/express-status-monitor#readme)
- [Project repository](https://github.com/RafalWilinski/express-status-monitor)
- [Release notes](https://github.com/RafalWilinski/express-status-monitor/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/rafalwilinski-express-status-monitor
