Building Pingvertex: A Solo-Built Uptime & API Monitoring Platform in Rust
Introduction
Over the past several months, I've been building Pingvertex — an uptime and API monitoring platform — completely solo. From architecture to deployment, every layer of this system was designed and implemented by me. In this post, I want to walk through the technical decisions behind it, the stack I used, and some of the challenges I ran into along the way.
What is Pingvertex?
Pingvertex is a monitoring platform that helps teams keep track of their services' health. It covers:
- Uptime checks — continuous monitoring of endpoints
- Incident management & alerting — automatic detection and notification when something breaks
- Status pages — public-facing pages showing system health
- Real User Monitoring (RUM) — tracking actual user experience data
- API flow / synthetic monitoring — simulating real user journeys against APIs
- Webhooks — for integrating with other tools
- Multi-tenant support — built to serve multiple organizations from one deployment
- Usage-based billing — so pricing scales with actual usage
The Tech Stack
I built Pingvertex with a strong focus on performance, reliability, and maintainability:
-
Backend: Rust, structured as a modular workspace — separate crates for
domain,application,infra,api,worker, andagent. This separation keeps business logic decoupled from infrastructure concerns and makes the codebase easier to test and extend. - Async runtime: Tokio, powering the concurrent checks and background workers that make real-time monitoring possible.
- Database: PostgreSQL for durable, relational storage of checks, incidents, and tenant data.
- Frontend: Leptos, a Rust-based web framework, used to build the dashboard — keeping the entire stack in one language.
- Containerization: Docker, for consistent builds and deployments.
- Observability: Prometheus and Alertmanager to monitor Pingvertex itself — because a monitoring tool should be able to monitor its own health too.
- OS/Infra: Linux-based deployment throughout.
Why This Architecture?
Splitting the backend into domain/application/infra/api/worker/agent crates was a deliberate choice. It means:
- Domain logic stays pure — no framework or database code leaking into core business rules.
- Testing is easier — each crate can be tested in isolation.
- The system can grow — new features (like RUM or synthetic monitoring) plug in without rewriting the core.
What I Learned
Building this solo — from database schema design to async worker orchestration to the frontend dashboard — pushed me to get hands-on with nearly every layer of a production system. A few key takeaways:
- Rust's type system catches a surprising number of bugs before they ever reach a running system.
- Designing multi-tenancy and usage-based billing from day one is far easier than retrofitting it later.
- Tokio's async model is powerful but requires careful thought around cancellation and backpressure, especially for long-running checks.
What's Next
I'm currently working on getting Pingvertex in front of early users and refining the platform based on real feedback. If you're interested in uptime/API monitoring, or just want to talk Rust architecture, I'd love to connect.
Top comments (0)