ServicePulse
A Spring Boot endpoint monitoring application that checks HTTP services, stores check history, and runs as a Docker Compose stack with PostgreSQL, Redis, Adminer, Caddy HTTPS, GitLab CI, and GCP deployment scripts.
Technical highlights
- HTTP endpoint monitoring with stored check history
- PostgreSQL persistence with Spring Data JPA
- Redis caching through Spring Cache
- Docker Compose environment with app, database, cache, Adminer, and reverse proxy
- Caddy reverse proxy with HTTPS termination
- GitLab CI pipeline for build, tests, and reports
- Deployment scripts for Google Compute Engine
- Local and cloud-oriented evaluation flow
Problem
I wanted to build more than a basic CRUD application. The goal was to create a small backend system that behaves like a real deployed service: it should monitor external URLs, store historical results, expose a dashboard, run behind HTTPS, use persistent services, and be deployable both locally and on a cloud VM.
My role
I designed and implemented the full project individually. I built the Spring Boot backend, Thymeleaf UI, PostgreSQL persistence, Redis caching, Docker Compose stack, Caddy reverse proxy setup, Adminer integration, GitLab CI pipeline, and GCP deployment scripts.
Architecture
ServicePulse uses a layered Spring Boot architecture. Controllers handle web and API requests, services contain monitoring logic, repositories manage persistence, and PostgreSQL stores targets and check results. Redis is used for caching. The application runs in Docker Compose together with PostgreSQL, Redis, Adminer, and Caddy. Caddy acts as the public entry point and terminates HTTPS before forwarding traffic to the Spring Boot container.
Hardest technical problem
The hardest part was not the endpoint-checking logic itself, but making the full system reliable as infrastructure. I originally tried to add internal TLS between Caddy and the Spring Boot container as an extra improvement. A self-signed keystore caused fragile TLS errors, including Windows line-ending related corruption. I decided to remove that optional complexity and keep TLS termination at Caddy, which was the more stable engineering choice.
What I learned
This project taught me that backend development does not stop when the application compiles. DNS, HTTPS, reverse proxies, Docker volumes, CI reports, environment variables, and deployment scripts all affect whether software is actually usable. I also learned that removing unnecessary complexity can be a better decision than forcing an unstable feature into a project.