ES

SkyFence

Monitors real aircraft over Spain with adsb.fi data, uses the Haversine formula to check whether any of them enters a sensitive zone (airports, military bases, nuclear power plants) and pushes the alert to the map instantly over WebSocket.

The challenge

Detect in real time when an aircraft or a drone enters the area around an airport, a military base or a nuclear power plant, and warn the operator without them having to reload anything.

Type
Personal project
Status
Finished, updated in October 2026
Areas
Backend, Frontend, DevSecOps
Technologies
  • Java 17
  • Spring Boot 3
  • PostgreSQL 16
  • WebSocket / STOMP
  • React 18
  • Leaflet
  • Resilience4j
  • Bucket4j
  • Prometheus + Grafana + Loki
  • Docker
  • GitHub Actions
  • CodeQL
  • SonarCloud

Interactive demo

Screenshots

From the project's real code. The ones marked as sample data use simulated data instead of the backend or real video.

SkyFence dashboard with a map of Spain, live aircraft, monitored zones and HIGH alerts
Real-time dashboard with real aircraft, monitored zones and alerts
SkyFence alert history with filters by severity, aircraft, zone, distance and time
Paginated, filterable alert history Sample data
SkyFence restricted zone management with type, coordinates and radius
Restricted zone management Sample data
SkyFence system health with the status of the API, PostgreSQL, adsb.fi and the STOMP broker
System health with Spring Actuator Sample data
Swagger documentation of the SkyFence REST API
REST API documented with SpringDoc OpenAPI

What it does

  • Queries adsb.fi every 10 seconds and checks every aircraft against all active zones
  • HIGH severity if the aircraft is in the inner half of the radius, MEDIUM in the rest
  • Zone manager in the UI: create and delete zones with immediate effect
  • Intrusion simulator with test drones to validate alerts end to end
  • Paginated, filterable alert history stored in PostgreSQL
  • Rate limiting with Bucket4j, retry and circuit breaker with Resilience4j

What I learned

  • CI pipeline with tests, CodeQL, secret scanning and a SonarCloud quality gate
  • Full observability: metrics with Micrometer and Prometheus, logs with Loki, dashboards in Grafana
  • Designing a service that stays up when the external API fails
  • Unit tests with Mockito and integration tests with MockMvc

The public deployment on Render and Vercel is down. On this page the demo reproduces the behaviour with simulated aircraft, using the real zones the project loads in its initial migration.

Technical decisions

Alerts over WebSocket with STOMP
They arrive instantly and the frontend only has to subscribe to a topic, instead of polling the API every few seconds.
Distance with the Haversine formula
It measures on the Earth's sphere, not on a plane. The logic lives in a service with unit tests.
Resilience4j in front of adsb.fi
If the external source fails, the system stays up: it retries and opens the circuit.
Rate limiting with Bucket4j
Abusive requests are cut off before they reach the database.
Prometheus, Grafana and Loki
Metrics and logs for a service that runs on its own, without logging into the server to check.
CodeQL, secret scanning and SonarCloud in CI
Every push goes through security and quality analysis before it is deployed.

How it's built

Click each piece to see what it does.

adsb.fi

Public source of ADS-B positions. The backend queries it every 10 seconds within a 250 nautical mile radius around the centre of the peninsula.