I wanted a small application I could take through the whole delivery process: write it, package it, test it, deploy it, and understand what happens when a release fails. Ops-Status gives that work a concrete purpose. It is being built to check selected services and report whether they responded, how long they took, and what failed when they did not.
The working foundation is a FastAPI service running locally and through Docker Compose. A first monitoring route now performs a timed HTTP check against Grafana and reports reachability, status code, and response latency. Multi-service configuration, automated tests, CI, Kubernetes staging, and AWS delivery are still ahead. This case study records the working checkpoints and the decisions shaping the next ones.
Current stack: Python, FastAPI, Uvicorn, HTTPX, Docker, and Docker Compose.
From local Python to a reproducible container
I started with two routes: / for basic service information and /health for the application's own health. I served them with Uvicorn, checked the HTTP responses with curl, and inspected the listening socket.
The container uses python:3.12-slim and runs the application as a non-root user. Uvicorn listens on port 8000 across the container's interfaces so requests can reach it through the published host port. Docker Compose gives the application a repeatable local start and stop workflow.
A simple check from the host is:
curl --include --fail --silent --show-error \
http://127.0.0.1:8000/healthThe documented baseline returned HTTP 200. That validates a useful chain: the application started, Uvicorn accepted the request, the container networking worked, and the route returned a response.

Docker Compose publishes the application on port 8000, the health endpoint returns HTTP 200, and the container executes as the non-root app user.
The health route answers whether Ops-Status itself responds. A separate /checks route now performs the first real monitoring action: it sends a timed request to Grafana and returns the target identity, reachability, HTTP status when available, and latency. Docker Compose supplies the target through environment variables, while a local .env file keeps machine-specific values out of source control and .env.example documents the required configuration.
Defining what a failed check means
The checker preserves more information than a green or red indicator. A target can respond with an unexpected HTTP status, fail DNS resolution, refuse a connection, or exceed a timeout. Those outcomes point to different investigations.
During validation, a stale Docker Compose host mapping produced a structured result with reachable: false, measured latency, and a connection-refused error. After correcting the mapping, the same route reported reachable: true, HTTP 302, and the response latency. The redirect is important: Grafana responded successfully even though it did not return HTTP 200.
The current implementation is intentionally narrow: one environment-configured target, one synchronous request, a five-second timeout, and generic request-error handling. The successful response exposes the target name and result without returning the full URL. The next iteration will support multiple services, sanitize and categorize failure details, and add tests for healthy responses, redirects, unexpected status codes, DNS failures, refused connections, and timeouts.
Promoting one release through different environments
The delivery goal is to build a versioned image once and promote that tested artifact through the environments.
Local Compose is the starting point. Floci is planned for AWS-compatible development and integration tests, so I can work on cloud interactions without keeping an AWS environment running continuously. Supported APIs and differences from AWS will need to be checked as each integration is added.
The homelab's k3s cluster will provide staging for the application, with probes, resource settings, configuration, and rollout exercises. The planned AWS deployment uses ECS Fargate, Terraform-managed infrastructure, and a controlled release with smoke tests and rollback. Floci tests will be one layer of evidence; actual AWS behavior will still need its own validation.
These are planned stages. The existing k3s cluster and homelab monitoring do not mean Ops-Status is deployed or instrumented there yet.
The next checkpoint
The next useful result is moving from one environment-configured target to multiple services and adding automated tests that reproduce both successful and failed checks. That will turn the working single-service prototype into a monitoring foundation worth taking through CI and deployment.

The /checks route confirms that the monitored Grafana service responded, preserves its HTTP 302 redirect, and records the request latency.
The project will continue through working checkpoints. At this stage, I have established the local application and container path, the first functioning external check, and environment-based configuration. The next work is making the monitoring behavior multi-service, testable, and repeatable before expanding the delivery pipeline.
Repository: github.com/Jeff-Fontenot/ops-status
