From a black box to a healthy production dashboard
How StratoFusion added useful VM observability without turning its web application into an infrastructure control panel.
A dashboard is easy to draw. A trustworthy dashboard is mostly a problem of boundaries.
StratoFusion runs its production application, database, transfer worker and observability services together on an authoritative virtual machine. That simplified the hosting model, but it also created an operational question: how could an administrator understand the health and capacity of that runtime without opening several separate tools or granting the web application dangerous control over the host?
The first answer was deliberately small: build a read-only infrastructure overview from monitoring data the system already produced.
A representative production snapshot under load. Capacity and queue signals are shown alongside host health so “busy” is not mistaken for “broken”.
The useful part of the work was not the progress bars. It was deciding what the feature must never become.
Begin with the operational question
The dashboard needed to answer a short list of questions:
- Is the application and its database reachable?
- Is the transfer worker healthy?
- Are Prometheus targets being scraped?
- How busy are CPU, memory and the root filesystem?
- How much transfer work is running or queued?
- Which exact application release is deployed?
- Is any value missing, stale or degraded?
That is enough to support routine diagnosis without pretending to replace Grafana, logs, alerts or direct operator access.
Scope matters here. An infrastructure page can easily accumulate buttons for restarting services, deploying releases, opening shells or changing schedules. Each button expands the application's authority and creates another mutation path to secure, audit and recover.
For the first slice, StratoFusion exposes no infrastructure mutations at all.
Keep control outside the web application
The Next.js application does not receive a Docker socket, SSH key, host-command capability, cloud-provider credential or private management URL. It cannot restart a container or power-cycle a VM.
Instead, it receives a narrow server-only address for Prometheus and a few non-secret display labels. The browser never sees the internal Prometheus URL. An authenticated admin route asks application services for a canonical overview, and those services collect health and metric snapshots through small ports.
That distinction is important:
Observing a system does not require giving the observer control over the system.
The UI renders a provider-neutral node summary. It knows about resources, service health, queue capacity, warnings and release metadata. It does not know how Prometheus query expressions work or how the transfer worker exposes metrics.
That keeps the React layer simple and leaves room for another metrics adapter later without redesigning the page.
Model one VM as the beginning of a fleet
Production currently has one authoritative runtime node, but the response is shaped as a list of nodes rather than a singleton object.
This is not an attempt to invent a distributed platform prematurely. It is a modest way to keep today's UI from becoming tomorrow's migration problem.
Each node contains:
- a stable application identifier;
- environment, provider and optional region labels;
- resource metrics with explicit availability state;
- observable service checks;
- transfer-worker queue capacity;
- the deployed release SHA;
- warning count and overall status;
- the time of the last useful observation.
The model is still intentionally small. It has no VM lifecycle API, scheduler controls or deployment commands. Adding a second node later means adding another adapter result, not changing what “infrastructure health” means to the browser.
Treat missing data as data
Monitoring integrations fail in ordinary ways. A query can time out. Prometheus may be absent from a developer environment. One scrape target may be down while the application and other targets remain healthy.
Returning zero in those cases would be actively misleading. Zero CPU usage and unavailable CPU data are not the same observation.
Every metric therefore carries an availability state and a sample time. The overview can distinguish:
- available — a current value was collected;
- stale — a value exists but is older than the accepted window;
- unavailable — no trustworthy value could be collected.
The overall node status follows the evidence. Missing critical metrics or a failed observable service degrades the node. If every source is unavailable, the node is unavailable. Partial data remains visible alongside a warning instead of causing the whole page to fail.
This fail-soft behaviour proved useful before the production deployment. On an ordinary local development server, Prometheus was not configured, so health checks could still render while capacity values clearly showed as unavailable. On the local VM rehearsal, Prometheus and its scrape targets were present, and the same interface became fully populated without a UI code change.
Use existing telemetry before adding new agents
The production stack already included Prometheus, a node exporter and transfer-worker metrics. The dashboard composes those sources instead of introducing another collector.
CPU, memory, filesystem, uptime and network rates come from node-exporter series. Queue depth, running operations, concurrency and queue limits come from the transfer worker. Prometheus target health supplies explicit checks for the exporter, worker metrics and Prometheus itself.
Application and database readiness use the application's existing server-side health path. Transfer-worker health uses its existing health client.
Reusing these sources has two advantages. The dashboard agrees with the monitoring system operators already trust, and the feature adds no new privileged process to the VM.
It also makes disagreement visible. If a direct worker health check succeeds while its Prometheus target is down, those are two different facts worth showing rather than merging into one green badge.
Make the release part of the image
An operational screen should identify the software it is describing.
Production images are built from an exact Git commit. The build writes that commit SHA into the container image, and the deployment selects the image by the same immutable SHA. The dashboard reads that embedded value and displays a shortened form.
There is no manually maintained “current version” field. A release label in an environment file would eventually drift from the actual image. The artifact is the authority for its own identity.
The local VM rehearsal caught precisely this kind of configuration problem: an empty environment value masked the SHA already embedded in the image. Removing the override restored the intended single source of truth. That small finding justified rehearsing the full deployment path rather than treating a successful local page render as sufficient evidence.
Rehearse the release, not only the feature
The dashboard was first exercised against a local VM stack with the same application, database, transfer worker, Prometheus and node exporter boundaries as production.
That rehearsal verified more than layout:
- the admin permission appeared only for configured administrators;
- the server could reach Prometheus through the Compose network;
- browser responses did not expose the internal metrics address;
- all observable targets reported independently;
- node labels described the local environment honestly;
- the deployed release could be traced to an immutable build;
- an environment-only change could recreate the application without replacing database volumes.
The production promotion then used the normal path: merge the reviewed development revision into the main branch, build immutable application and worker images, allow the worker drain gate to protect active transfers, roll the stack, wait for health and verify the signed-in production page.
The result was not merely “the route returns 200.” The live page showed the expected release, current host capacity, idle worker queue, zero warnings and five healthy observable services.
Test policy as well as presentation
The focused test suite covers several layers:
- the admin route rejects unauthenticated and non-admin requests;
- the overview service combines partial metric and health results correctly;
- Prometheus responses are parsed and unavailable values remain explicit;
- service failures degrade rather than crash the response;
- the hook handles loading, refresh and errors;
- the view renders healthy, degraded and unavailable states;
- navigation exposes the page only to administrators.
Those tests matter more than a screenshot of the happy path. An observability tool earns trust by describing failure accurately.
What the dashboard intentionally does not solve
This first slice is not a fleet manager. It cannot deploy code, restart containers, change queues, manage backups, open a private console or alter VM state.
It also does not replace alerting, detailed Grafana exploration, structured logs or the production runbook. Its job is orientation: show the current state, show what is unknown, and give an administrator enough context to choose the correct deeper tool.
That restraint is part of the feature, not unfinished polish.
The broader lesson
Operational UI should reduce uncertainty without quietly expanding authority.
A small read-only projection over existing telemetry delivered most of the day-to-day value. Explicit unavailable states kept the display honest. Stable ports kept monitoring details out of the UI. Immutable image metadata made release identity automatic. A local VM rehearsal exposed configuration drift before production.
The finished dashboard looks straightforward. That is a good outcome. The complexity is contained behind boundaries the page does not need to explain.
Building systems like this?
Continue the engineering conversation
Read more about Richard's approach to architecture, product judgement and building maintainable independent software.
Continue reading
Engineering notes
Why StratoFusion moved production to one VM
Read nextEngineering notes

