UptraceIQ
A system health and uptime monitoring platform that runs parallel endpoint health checks, archives metrics to S3, and fires Lambda-formatted SNS email alerts on status transitions — Java Spring Boot backend, React dashboard, full AWS stack
Tech Stack
Context
The Problem
Most portfolio projects stop at CRUD. The goal here was to build something that exercises the patterns production observability tools actually use: parallel I/O, status-transition alerting, cold storage archival, and configurable per-endpoint sensitivity — against real AWS managed services.
Constraints
- Health checks must run in parallel, not sequentially, to scale with the endpoint list
- Must support both local development (H2) and production (AWS RDS) without code changes
- Alerts must fire only on status transitions, not on every failed check
- Old metrics must roll off RDS automatically so the primary store stays lean
- Dashboard must auto-refresh and support dark mode end-to-end
Stakes
Built to demonstrate fluency with Spring Boot, the AWS managed-services stack, and React 19 in a single coherent system rather than isolated demos
My Role
Title
Full-Stack Software Engineer
Team
Personal Project
Ownership
End-to-end ownership: Spring Boot backend, parallel health-check engine, RDS schema, S3 archival job, Lambda/SNS alerting, React dashboard, and Spring Profiles configuration
Approach & Key Decisions
HealthCheckService pings every endpoint in parallel via CompletableFuture every 30 seconds. Results persist to RDS Postgres; when status transitions are detected, AlertService invokes Lambda to format an alert and publishes through SNS for email delivery. A scheduled MetricsArchiveService exports anything older than 7 days to S3, keeping RDS lean. The React 19 + Vite dashboard consumes a Spring REST API via React Query, with Recharts sparklines, status badges, and a class-based Tailwind v4 dark mode.
CompletableFuture for parallel health checks
Sequential pings would scale linearly with endpoint count. Parallel execution keeps the 30-second cycle time stable as the monitored fleet grows.
Lambda + SNS for alert delivery rather than emailing directly from Spring
Decouples message formatting from the core service and uses AWS's delivery guarantees. SNS handles retries and subscription fan-out so the monitor doesn't have to.
Spring Profiles for H2 vs RDS
Local dev runs against H2 with zero setup; production points at RDS — no conditional logic in code, just a profile flag.
Daily S3 archival of metrics older than 7 days
Keeps the operational store small and fast while preserving full history in cheap object storage for later analysis.
DTO layer separating API contract from JPA entities
Lets the database schema evolve without breaking the frontend, and prevents accidentally exposing internal fields over the API.
Challenges & Solutions
⚠Challenge
Tracking failure streaks across parallel health checks safely
✓Solution
Used ConcurrentHashMap for in-memory streak counters so multiple CompletableFutures can update state without locking
⚠Challenge
Cascading delete from endpoint to historical results
✓Solution
Configured JPA cascade so deleting an endpoint cleans up its result rows in order, avoiding foreign-key violations
⚠Challenge
Toggling dark mode without a full re-render or flash
✓Solution
Adopted Tailwind v4's class-based dark variant for instant, theme-wide switching across every component
⚠Challenge
Running the same code against H2 locally and RDS in production
✓Solution
Used Spring Profiles to swap datasource configuration externally — no conditional code paths inside the application
Outcomes & Impact
Check Interval
Endpoints pinged every 30 seconds in parallel via CompletableFuture
Dashboard Refresh
React Query auto-refresh every 5 seconds with sparkline visualizations and full dark mode
Storage Strategy
Metrics older than 7 days roll off RDS to S3 automatically, keeping the operational store lean
Alerting Pipeline
Status transitions trigger Lambda-formatted email alerts through SNS
Delivery
Built across 8 incremental phases from January to April 2026