Complete System Architecture

A comprehensive technical overview of PlaneTrack.ai's real-time aircraft tracking infrastructure - from ADS-B receivers to your browser

Table of Contents

1. System Overview

PlaneTrack.ai is a production-grade flight tracking platform that processes real-time ADS-B (Automatic Dependent Surveillance-Broadcast) data from aircraft worldwide. The system ingests data from multiple sources, processes and stores it in PostgreSQL, and serves it through a modern React web application with live map visualization.

Data Sources

2

OpenSky Network & ADSBHub

Live Aircraft

10k+

Tracked simultaneously

Message Rate

50k/s

Peak throughput

Update Frequency

15s

Real-time refresh

Storage

73TB

Total capacity

Services

9

Running systemd units

2. Complete Data Flow

End-to-end journey of ADS-B data from aircraft transponders to user's browser

✈️ Aircraft

ADS-B Transponders

1090 MHz broadcasts

📡 Receivers

Ground Stations

RTL-SDR, FlightAware

🌐 Networks

OpenSky & ADSBHub

Global aggregation

📨 Redpanda Cluster

Kafka-compatible streaming

3 brokers: 10.0.3.24, 10.0.3.108, 10.0.3.50

⚙️ Aggregator

adsb_snapshot_aggregator.py

Groups aircraft positions

📝 Writer

adsb_unified_writer.py

Batch inserts: 2000/batch

🗄️ PostgreSQL 16

adsb_production database

Host: 10.0.3.235:5432

🔌 adsb-api

FastAPI on :3001

Read-only data API

🔐 auth-admin-api

FastAPI on :8080

Auth & admin

🚀 production-api

Flask/Gunicorn on :9003

Main API server

🌐 Nginx

Reverse Proxy & SSL

planetrack.ai:443

⚛️ React Frontend

TypeScript + Vite

MapLibre GL visualization

3. Systemd Services

All background services managed by systemd for automatic startup and recovery

Service Port Script Purpose Status
adsb-snapshot-aggregator - adsb_snapshot_aggregator.py Aggregates raw ADS-B from Kafka → adsb_snapshot topic Running
adsb-unified-writer - adsb_unified_writer.py Writes Kafka snapshots to PostgreSQL tables Running
adsb-api 3001 adsb_api.py FastAPI read-only data API (live aircraft, tracks) Running
auth-admin-api 8080 main_api.py Authentication, admin, Stripe billing Running
planetrack-api-1 9003 production_api.py Primary Flask API (gunicorn + gevent) Running
planetrack-api-2 9004 production_api.py Backup Flask API for failover Running
flight-snapshot - flight_snapshot_service.py 5-minute snapshots with flight duration/routes Running
system-status-api 9999 system_status_api.py Health metrics for dashboards Running

4. Data Ingestion Layer

Data Sources

OpenSky Network

Kafka Topic: adsb_snapshot

Format: JSON snapshots

Rate: ~30k messages/min

  • Primary data source
  • Global coverage from 5000+ receivers
  • Position, altitude, velocity, heading
  • Aircraft registration & type codes
  • Historical data access

ADSBHub.org

Kafka Topic: adsb.raw

Format: BaseStation/SBS CSV

Rate: ~50k messages/sec peak

  • Secondary/backup source
  • MSG types 1-8 (all message types)
  • Real-time raw feed
  • Coverage gap filling
  • Redundancy & validation

Redpanda Message Queue

Kafka-Compatible Streaming Platform

Cluster: 3 brokers for high availability

Broker 1: 10.0.3.24:9092 Broker 2: 10.0.3.108:9092 Broker 3: 10.0.3.50:9092

Topics:

  • adsb_snapshot - Aggregated aircraft positions (1 partition, 3 replicas)
  • adsb.raw - Raw BaseStation format from ADSBHub (1 partition, 3 replicas)

Benefits:

  • Decoupling: Data sources independent from consumers
  • Buffering: Handles traffic spikes & consumer downtime
  • Replayability: Can reprocess historical messages
  • Durability: 3x replication across brokers

Processing Scripts

adsb_snapshot_aggregator.py

Consumes raw BaseStation messages from adsb.raw topic

  • Groups by aircraft (icao24)
  • Keeps latest position per aircraft
  • Publishes aggregated snapshot every 15 seconds
  • Outputs to adsb_snapshot topic

adsb_unified_writer.py

Writes aggregated snapshots to PostgreSQL

  • Batch processing: 2000 records per batch
  • 800ms batch window
  • Writes to adsb_points_partitioned table
  • Upserts to aircraft_state for fast lookups
  • Automatic partition creation

flight_snapshot_service.py

Creates detailed flight snapshots every 5 minutes

  • Captures all ~10,000 live flights
  • Calculates flight duration from route progress
  • Stores route info (origin/destination)
  • Used for "Longest Flight" feature
  • Historical flight analysis

5. Database Architecture

PostgreSQL Configuration

Host: 10.0.3.235 Port: 5432 Database: adsb_production Version: PostgreSQL 16 Users: - adsb_prod_user (primary application user) - adsb_writer (write-only for ingestion) - web_anon (read-only for PostgREST)

Storage Tiers

🔥
Hot Storage (ts_hot)

Location: Local NVMe SSD

Retention: Today + yesterday (2-3 days)

Size: ~50-75 GB

Purpose: Real-time queries, live aircraft tracking

📦
Archive Storage (ts_archive)

Location: Local SATA drives

Retention: Last 30 days

Size: ~700-800 GB

Purpose: Recent history queries, track analysis

❄️
Cold Storage (ts_cold)

Location: NAS at /mnt/nas_pg/planetrackai/pg_ts

Retention: 30+ days (unlimited)

Capacity: 73 TB total

Purpose: Historical data, analytics, compliance

Core Tables

aircraft_state

Current state of each aircraft (fast lookup)

  • icao24 (PRIMARY KEY)
  • callsign, lat, lon, altitude
  • heading, velocity, vertical_rate
  • last_seen timestamp
  • Updated via UPSERT on each batch

adsb_points_partitioned

Historical position data (partitioned by day)

  • received_at, icao24, callsign
  • lat, lon, altitude, heading, velocity
  • vertical_rate, onground, alert, spi
  • Daily partitions: adsb_points_part_YYYYMMDD
  • Millions of records per day

flight_snapshots

5-minute flight state snapshots

  • snapshot_time, hex_ident, callsign
  • lat, lon, altitude, speed, heading
  • departure_airport, arrival_airport
  • flight_duration_minutes
  • distance_total_nm, distance_remaining_nm
  • progress_percent, airline, category

active_flights

Currently active flight tracking

  • hex_ident, callsign
  • departure_time, first_seen, last_updated
  • origin_icao, dest_icao
  • distance_remaining_nm, progress_percent
  • flight_phase (climb/cruise/descent)

route_reference

Known flight routes and airlines

  • callsign (lookup key)
  • origin_icao, origin_name, origin_city
  • dest_icao, dest_name, dest_city
  • great_circle_distance_nm
  • airline_name

faa_aircraft

FAA registry data for US aircraft

  • mode_s_code_hex (ICAO address)
  • n_number (registration)
  • type_aircraft, manufacturer
  • model, serial_number
  • owner_name, owner_city

Materialized Views

latest_flight_snapshot

Latest position for each aircraft - used for fast live queries

CREATE MATERIALIZED VIEW latest_flight_snapshot AS SELECT DISTINCT ON (hex_ident) hex_ident, callsign, lat, lon, altitude, speed, heading, received_at FROM aircraft_state WHERE received_at > now() - interval '2 minutes' ORDER BY hex_ident, received_at DESC;

Refreshed automatically by the unified writer after each batch

Partitioning Strategy

Daily Partitions with Auto-Rotation

  • Partitioned by received_at (daily boundaries, UTC)
  • Auto-creation for yesterday/today/tomorrow via ensure_adsb_points_partition()
  • Nightly cron job (00:15) moves 30+ day partitions to cold storage
  • Partition pruning enables fast queries within date ranges
-- Partition naming convention adsb_points_part_20260120 (today - ts_hot) adsb_points_part_20260119 (yesterday - ts_hot) adsb_points_part_20251221 (30 days ago - ts_cold)

6. API Layer

Read-Only Data API (adsb_api.py)

Port 3001 - FastAPI with Uvicorn

High-performance read-only API for live aircraft data

GET /rpc/live_aircraft?window_secs=120&max_rows=30000 → Returns all aircraft with positions in last 120 seconds → Response: [{ icao24, callsign, lat, lon, altitude, heading, velocity, last_seen }] GET /rpc/track?icao24={hex}&minutes=30&max_rows=2000 → Returns flight track history (breadcrumb trail) → Response: [{ icao24, lat, lon, altitude, velocity, received_at }] GET /rpc/search?q={query}&limit_n=20 → Search aircraft by hex code or callsign → Response: [{ icao24, callsign, last_seen, lat, lon }] GET /rpc/longest_flight → Aircraft with longest current flight duration → Response: { hex, callsign, flight_time_minutes, departure_airport, arrival_airport } GET /rpc/stats → System statistics → Response: { rows_1m, freshness_ms, live_aircraft }

Production API (production_api.py)

Port 9003 - Flask with Gunicorn + Gevent

Main production API with advanced features

Configuration: - Workers: 2 gevent workers - Connections: 1000 per worker - Max requests: 1000 before worker recycle Endpoints: GET /api/rpc/live_aircraft → Live aircraft with oceanic predictions GET /api/rpc/track → Flight track with stitching GET /api/rpc/longest_flight → Longest flight from snapshots GET /api/route/{callsign} → Route information GET /api/flight/{callsign}/status → Flight status with ETA GET /api/aircraft_lookup/{hex} → Aircraft photos & registration

Auth & Admin API (main_api.py)

Port 8080 - FastAPI with Authentication

POST /auth/login → User login POST /auth/register → Create new account GET /auth/me → Get current user info POST /stripe/create-checkout-session → Start Stripe payment POST /stripe/webhook → Handle Stripe webhooks Admin pages (HTTP Basic Auth protected): - /admin.html → Dashboard - /admin-users.html → User management - /admin-database.html → Database stats - /admin-data.html → Data management - /admin-providers.html → Data provider tools - /admin-system.html → System configuration

Rate Limiting Tiers

Free Tier

1/s

100 requests/day

Starter ($9/mo)

10/s

10,000 requests/day

Professional ($29/mo)

100/s

100,000 requests/day

Enterprise

1000/s

Unlimited requests

7. Frontend Architecture

Technology Stack

React 18 TypeScript Vite MapLibre GL Zustand React Query Tailwind CSS Framer Motion Lucide Icons

Project Structure

/home/tristanmunday/psql/website/test/src/ ├── App.tsx # Root application component ├── main.tsx # Vite entry point ├── index.css # Global styles (Tailwind) │ ├── components/ # React components │ ├── aircraft/ │ │ └── DetailPanel.tsx # Aircraft details, route, history │ ├── layout/ │ │ └── Header.tsx # Top navigation bar │ ├── map/ │ │ ├── FlightMap.tsx # MapLibre GL map with aircraft │ │ └── MapControls.tsx # Style, 3D, terrain toggles │ ├── search/ │ │ └── SearchBar.tsx # Aircraft search interface │ ├── stats/ │ │ └── StatsBar.tsx # Statistics display │ └── ui/ │ └── Toast.tsx # Notification toasts │ ├── hooks/ │ └── useAircraftData.ts # React Query data fetching hooks │ ├── services/ │ ├── api.ts # API client functions │ ├── airports.ts # Airport lookup database │ ├── trackStitching.ts # Multi-leg track handling │ └── flightLegService.ts # Flight leg detection │ ├── stores/ # Zustand state management │ ├── aircraftStore.ts # Aircraft state & selection │ ├── mapStore.ts # Map configuration │ └── uiStore.ts # UI state (toasts) │ ├── types/ │ ├── api.ts # API response types │ └── aircraft.ts # Domain types │ └── utils/ ├── formatters.ts # Number/distance formatting ├── geo.ts # Geographic calculations ├── greatCircle.ts # Great circle math └── antimeridian.ts # International date line

Key Components

FlightMap.tsx

Main map rendering component

  • MapLibre GL for WebGL rendering
  • Custom SVG aircraft icons with rotation
  • Three map styles: Dark, Light, Satellite
  • Track visualization (breadcrumb trail)
  • Route line with antimeridian handling
  • Smooth aircraft interpolation

DetailPanel.tsx

Aircraft information display

  • Callsign, hex code, altitude, speed
  • Route (origin → destination airports)
  • Flight duration and progress bar
  • Aircraft photos & registration lookup
  • Flight history table
  • Track view toggle (current leg / all)

StatsBar.tsx

Live statistics display

  • Total aircraft count
  • Category breakdown (Commercial, Military, etc.)
  • Emergency aircraft alerts
  • Fastest aircraft
  • Highest altitude aircraft
  • Longest flight duration

SearchBar.tsx

Real-time aircraft search

  • Search by hex code or callsign
  • Instant results as you type
  • Click to select and track
  • Recent searches history

State Management (Zustand)

aircraftStore

  • Aircraft Map (hex → Aircraft object)
  • Selected aircraft hex & details
  • Track points for selected aircraft
  • Statistics (fastest, highest, longest)
  • Category filter state
  • Track view mode (current leg / all)
  • Interpolation data for smooth movement

mapStore

  • Map center [longitude, latitude]
  • Zoom level
  • Map style (dark/light/satellite)
  • 3D mode enabled
  • Labels visible
  • Terrain visible

uiStore

  • Toast notifications array
  • Search open state
  • Detail panel open state
  • Stats expanded state

Data Fetching (React Query)

Automatic Background Updates

  • Live Aircraft: Fetches every 15 seconds, 60s stale time
  • Oceanic Predictions: Fetches every 60 seconds (after live data loaded)
  • Track History: Fetches on aircraft selection, 30s stale time
  • Aircraft Lookup: Fetches photos/registration, 60s stale time
  • Flight Route: Cascading API calls with 5-minute cache
  • Longest Flight: Fetches every 30 seconds

Aircraft Category Detection

Hybrid Classification System

  • Hex Prefixes: Military ICAO country blocks (ae, af, 43c, etc.)
  • Callsign Patterns: Commercial ICAO codes (AAL, UAL, DAL, etc.)
  • Military Callsigns: RCH, DUKE, NAVY, ARMY, RAF, etc.
  • Cargo Airlines: FDX, UPS, DHL, etc.
  • N-Numbers: US private registrations (N12345)
  • Emergency: Squawk codes 7700, 7600, 7500

Categories: commercial | private | military | cargo | emergency | unknown

8. Nginx & Infrastructure

Nginx Configuration

Server: planetrack.ai, www.planetrack.ai Listen: 80 (redirect to HTTPS), 443 (HTTP/2) SSL/TLS: - Certificates: Cloudflare Origin (/etc/ssl/cloudflare/) - Protocols: TLSv1.2, TLSv1.3 - Session caching: 10 minutes - OCSP Stapling: Enabled Security Headers: - Strict-Transport-Security: max-age=31536000 - X-Frame-Options: SAMEORIGIN - X-Content-Type-Options: nosniff - X-XSS-Protection: 1; mode=block - Content-Security-Policy: (comprehensive policy) Routing: - /api/* → proxy to 127.0.0.1:9003 (planetrack-api-1) - /rpc/* → proxy to 127.0.0.1:9003 - /admin*.html → proxy to 127.0.0.1:8080 (auth-admin-api) - /* → static files from /home/tristanmunday/psql/website/ Real IP: - Cloudflare CF-Connecting-IP header extraction

Cron Jobs

# Daily ADS-B backup at 1:00 AM 0 1 * * * /usr/local/bin/backup_adsb.sh # Flight history processing at 1:30 AM 30 1 * * * /home/tristanmunday/psql/website/process_daily_flights.sh # Flight history monitoring every 15 minutes */15 * * * * /home/tristanmunday/psql/website/monitor_flight_history.sh # System config backup at 3:00 AM 0 3 * * * /home/tristanmunday/psql/website/backup_system_config.sh

File Locations

Configuration: - Nginx: /etc/nginx/sites-enabled/planetrack.ai - Systemd: /etc/systemd/system/*.service - SSL Certs: /etc/ssl/cloudflare/ Application: - Backend: /home/tristanmunday/psql/ - Frontend: /home/tristanmunday/psql/website/ - React Source: /home/tristanmunday/psql/website/test/src/ - Production API: /home/tristanmunday/planetrack.ai-production/app/ Logs: - Nginx: /var/log/nginx/ - Flight Snapshot: /home/tristanmunday/psql/logs/ - Systemd: journalctl -u [service-name]

9. Monitoring & Operations

System Status API

Port: 9999

File: system_status_api.py

  • Real-time service health checks
  • Database connectivity status
  • Kafka consumer lag
  • Disk usage monitoring
  • HTTP Basic Auth protected

Prometheus Metrics

Port: 9090

  • Time-series metrics database
  • 15-day retention
  • 15-second scrape interval
  • Custom ADSB metrics exporter

Grafana Dashboards

Port: 3000

  • Ingestion rate graphs
  • Database size trends
  • API response times
  • Service health overview

Auto-Recovery

File: monitor_and_recover.py

  • Detects service failures
  • Automatic restarts
  • Ingestion stall detection
  • Alert notifications

Critical Alerts

Ingestion Stopped

⚠️

No messages for 5+ min

Database Down

⚠️

Cannot connect to PostgreSQL

Disk Critical

⚠️

Less than 5% free space

API Down

⚠️

Not responding 3+ min

10. Complete Technology Stack

Backend

Python 3.12 FastAPI Flask Gunicorn Uvicorn Gevent PostgreSQL 16 psycopg3 Redpanda/Kafka confluent-kafka bcrypt Stripe SDK

Frontend

React 18 TypeScript Vite MapLibre GL JS Zustand React Query Tailwind CSS Framer Motion Lucide Icons

Infrastructure

Ubuntu Linux Nginx systemd Cloudflare SSL Prometheus Grafana Cron

Data Sources

OpenSky Network ADSBHub.org FAA Aircraft Registry ADSBDB

System Status

Monitor real-time system health, service status, and performance metrics

View System Status → Back to Map →