-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture Overview
This document provides a comprehensive overview of the tail-lookup system architecture, design decisions, and component interactions.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Clients β
β (Web Browser, API Consumers, Mobile Apps, Scripts) β
βββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β
β HTTP/REST
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FastAPI Application β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β API Endpoints β β
β β β’ GET /api/v1/aircraft/{tail} β β
β β β’ POST /api/v1/aircraft/bulk β β
β β β’ GET /api/v1/health β β
β β β’ GET /api/v1/stats β β
β β β’ GET / (Web UI) β β
β ββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ β
β β Pydantic Models β β
β β (Request/Response Validation & Serialization) β β
β ββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ β
β β Database Layer (database.py) β β
β β β’ N-number normalization β β
β β β’ Aircraft/Engine type mappings β β
β β β’ JOIN optimization β β
β ββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SQLite Database β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β master table (~300K records) β β
β β β’ n_number, mfr_mdl_code, year_mfr, etc. β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β acftref table (Aircraft model reference) β β
β β β’ code, mfr, model, type_acft, type_eng, etc. β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β metadata table (Update tracking) β β
β β β’ key, value (last_updated timestamp) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
Client Request:
GET /api/v1/aircraft/N172SP -
FastAPI Routing: Route handler in
main.pyreceives request - N-number Normalization: Convert "N172SP" β "172SP" (strip N prefix, uppercase)
-
Database Query: Execute JOIN query between
masterandacftreftables - Type Mapping: Convert numeric codes to human-readable strings (e.g., "4" β "Fixed Wing Single-Engine")
- Response Validation: Pydantic model validates and serializes response
- Client Response: JSON with aircraft details or 404 if not found
-
Client Request:
POST /api/v1/aircraft/bulkwith JSON array of tail numbers - Request Validation: Pydantic validates max 50 tail numbers
- Batch Processing: Iterate through each tail number
- Individual Lookups: Same lookup flow as single, but collect all results
- Error Handling: Failed lookups return with error message, don't fail entire request
- Response Aggregation: Return total count, found count, and results array
- Client Response: JSON with bulk results
- Scheduled Trigger: GitHub Actions cron at 6 AM UTC daily
- Download FAA Data: Fetch ReleasableAircraft.zip (~30MB)
- Parse MASTER.txt: Extract ~300K aircraft registrations
- Parse ACFTREF.txt: Extract aircraft model reference data
- Build SQLite Database: Create tables, insert data, create indexes
- Docker Build: Bake database into Docker image
-
Publish: Push to Docker Hub with
latestand date tags - Release: Create GitHub Release with database file attachment
- Optional Webhook: Trigger Portainer for auto-deployment
Purpose: Main application entry point, route definitions, middleware configuration
Key Features:
- CORS middleware for cross-origin requests
- Lifespan context manager for database connection handling
- N-number normalization function
- OpenAPI/Swagger automatic documentation
- Static file serving for web UI
Design Decisions:
- Why FastAPI? Modern async framework, automatic OpenAPI docs, excellent performance, Pydantic integration
- Why CORS enabled? Allow web apps from different origins to use the API
- Why lifespan context? Clean database connection management, proper startup/shutdown
Purpose: SQLite operations, type mappings, data access abstraction
Key Features:
- Singleton database connection pattern
- Aircraft type code to name mapping (11 types)
- Engine type code to name mapping (12 types)
- JOIN optimization between master and acftref tables
- Optional field handling (None for missing data)
Design Decisions:
- Why SQLite? Lightweight (~25MB), zero configuration, baked into Docker image, sufficient for read-heavy workload
- Why JOIN query? Single query is more efficient than multiple lookups
- Why code mappings in Python? FAA database has numeric codes, we provide human-readable names
Database Schema:
-- master table
CREATE TABLE master (
n_number TEXT PRIMARY KEY,
serial_number TEXT,
mfr_mdl_code TEXT,
year_mfr INTEGER,
-- ... other fields
);
-- acftref table
CREATE TABLE acftref (
code TEXT PRIMARY KEY,
mfr TEXT,
model TEXT,
type_acft TEXT,
type_eng TEXT,
no_eng INTEGER,
no_seats INTEGER,
-- ... other fields
);
-- metadata table
CREATE TABLE metadata (
key TEXT PRIMARY KEY,
value TEXT
);
-- Index for JOIN optimization
CREATE INDEX idx_mfr_mdl_code ON master(mfr_mdl_code);Purpose: Type-safe request/response models, validation, serialization
Models:
-
AircraftResponse: Single aircraft lookup response -
BulkRequest: Bulk lookup request (max 50 tail numbers) -
BulkResult: Single result within bulk response -
BulkResponse: Bulk lookup response with counts and results -
HealthResponse: Health check response -
StatsResponse: Database statistics response
Design Decisions:
- Why Pydantic? Automatic validation, serialization, OpenAPI schema generation
- Why Optional fields? Not all aircraft have all data (e.g., year_mfr may be unknown)
- Why max 50 for bulk? Balance between usability and server load
Purpose: Download FAA data, parse files, build SQLite database
Process:
- Download ReleasableAircraft.zip from FAA website
- Extract MASTER.txt (fixed-width format)
- Extract ACFTREF.txt (fixed-width format)
- Parse both files using column positions
- Create SQLite database with three tables
- Insert all records in batch for performance
- Create index on mfr_mdl_code for JOIN optimization
- Store last_updated timestamp in metadata table
Design Decisions:
- Why fixed-width parsing? FAA format is fixed-width, not CSV
- Why batch insert? Much faster than individual inserts (~300K records)
- Why index on mfr_mdl_code? This is the JOIN key, indexing improves query performance
- Why store metadata? Track when data was last updated for health checks
FAA Data Format:
- MASTER.txt: Fixed-width columns, ~300K rows, aircraft registration data
- ACFTREF.txt: Fixed-width columns, aircraft model reference
- Updated daily by FAA at 11:30 PM CT (5:30 AM UTC)
- Download URL: https://www.faa.gov/licenses_certificates/aircraft_certification/aircraft_registry/releasable_aircraft_download
Purpose: Browser-based interface for testing the API
Features:
- Dark theme (Tailwind-inspired colors)
- Tab-based interface (Single/Bulk lookup)
- Real-time validation
- Error handling with user-friendly messages
- Responsive design for mobile
- Database statistics display
Design Decisions:
- Why single-file HTML? Simple, no build process, easy to maintain
- Why dark theme? Modern aesthetic, easier on eyes
- Why tabs? Clear separation of single vs bulk lookup
Base Image: python:3.12-slim
Port: 8080
Health Check: HTTP GET to /api/v1/health every 30s
Container Contents:
- Python application code (
/app/app/) - SQLite database (
/app/data/aircraft.db) - Python dependencies (FastAPI, Uvicorn, Pydantic)
Design Decisions:
- Why baked-in database? Zero-configuration deployment, no external database needed
- Why slim image? Smaller image size (~150MB vs ~1GB for full Python image)
- Why port 8080? Standard non-privileged port, easily mappable
See CI/CD Pipeline for detailed workflow documentation.
Primary Workflows:
-
Nightly Build (
nightly-build.yml): Daily at 6 AM UTC -
Main Branch Build (
build-main.yml): On push to main, handles versioning and releases -
Develop Branch Build (
build-develop.yml): On push to develop branch
Design Decisions:
- Why 6 AM UTC? FAA updates at 11:30 PM CT (5:30 AM UTC), 30min buffer
- Why two workflows? Separate concerns: data updates vs code changes
- Why Docker Hub? Popular, reliable, free for public images
- Why GitHub Releases? Provide database snapshots for manual download
- SQLite read performance: Excellent for read-heavy workloads (~1000s queries/sec)
- JOIN optimization: Index on mfr_mdl_code improves JOIN performance
- File-based: No network latency, database is local to application
- Size: ~25MB database, easily fits in memory for OS-level caching
- Async FastAPI: Non-blocking I/O, handles concurrent requests efficiently
- Pydantic validation: Fast native validation, minimal overhead
- Static typing: Python 3.12 type hints improve performance
- Uvicorn: High-performance ASGI server
Current Design:
- Single container handles ~1000s requests/sec (read-only workload)
- Database fits in memory on most systems
- No external dependencies or network calls
Scaling Options:
- Horizontal scaling: Run multiple containers behind load balancer
- CDN caching: Cache responses for common tail numbers
- Read replicas: Distribute database file to multiple containers
- PostgreSQL migration: If write workload increases or multi-container writes needed
- No authentication required: Public FAA data, open access by design
- CORS enabled: Allow cross-origin requests
- Input validation: Pydantic validates all inputs
- SQL injection: Using parameterized queries, safe from injection
- Non-root user: Container runs as non-root (TODO: verify in Dockerfile)
- Minimal base image: python:3.12-slim reduces attack surface
- No secrets in image: No credentials or API keys
- Read-only database: Database is read-only, no write operations
- GitHub Actions permissions: Minimal permissions (contents:write, packages:write)
- Secrets management: Docker Hub credentials stored as GitHub Secrets
- Renovate: Automated dependency updates with intelligent scheduling and auto-merge capabilities
- Caching layer: Redis for frequently requested tail numbers
- Rate limiting: Prevent abuse of bulk endpoint
- API authentication: Optional API keys for tracking/quotas
- WebSocket updates: Real-time notifications of database updates
- Search functionality: Search by manufacturer, model, year
- Historical data: Track changes over time
- Multi-region deployment: Deploy to multiple regions for lower latency
- Monitoring: Prometheus metrics, Grafana dashboards
- PostgreSQL option: Alternative backend for high-concurrency workloads
- Single database file: No real-time updates, requires container restart
- No write API: Read-only by design
- US registrations only: FAA data only covers US-registered aircraft
- No historical data: Only current registrations, no change tracking
- Bulk limit: Max 50 tail numbers per request
π View on GitHub | π³ Docker Hub | π Report Issue | π¬ Discussions
License: MIT | FAA Data: Public Domain
π Getting Started
π Documentation
π³ Deployment
π§ Development
π Links