Database Models

πŸ—„οΈ Database Architecture

Comprehensive documentation of the SkySpy database schema, including all models, relationships, indexes, and performance considerations.


πŸ“‘ Quick Navigation

SectionDescription
OverviewDatabase engine & configuration
Entity RelationshipsVisual schema diagram
Domain GroupsModel organization
Model ReferenceDetailed field documentation
PerformanceIndexes & query tips
Data RetentionArchival strategies
MigrationsSchema management
MonitoringHealth metrics
Backup & RecoveryDisaster recovery

πŸ“Š Overview

SkySpy uses PostgreSQL as its primary database engine for production deployments, with SQLite supported for development and lightweight installations. The database schema is managed through Django's ORM and migrations system.

Key Characteristics

AspectDetails
🐘 Primary DatabasePostgreSQL 14+
πŸ“¦ Development DatabaseSQLite (optional)
πŸ”§ ORMDjango 5.x
πŸ”„ Connection PoolingCONN_MAX_AGE=60
πŸ“‹ Schema ManagementDjango Migrations

Database Configuration

# Production (PostgreSQL)
DATABASE_URL=postgresql://user:password@host:5432/adsb

# Development (SQLite)
DATABASE_URL=sqlite:///db.sqlite3

πŸ”— Entity Relationship Diagram

erDiagram
    %% ═══════════════════════════════════════════════════
    %% CORE AIRCRAFT TRACKING
    %% ═══════════════════════════════════════════════════
    AircraftSighting ||--o{ AircraftSession : "belongs to"
    AircraftSession ||--o| SessionTrackingQuality : "has quality metrics"
    AircraftSession ||--o{ PersonalRecord : "sets"
    AircraftSession ||--o{ RareSighting : "triggers"

    AircraftInfo ||--o{ AirframeSourceData : "has source data"

    %% ═══════════════════════════════════════════════════
    %% USER & AUTHENTICATION
    %% ═══════════════════════════════════════════════════
    User ||--o| SkyspyUser : "has profile"
    User ||--o{ UserRole : "has roles"
    Role ||--o{ UserRole : "assigned to"
    Role ||--o{ OIDCClaimMapping : "mapped from"
    User ||--o{ APIKey : "owns"
    User ||--o{ AircraftFavorite : "favorites"

    %% ═══════════════════════════════════════════════════
    %% ALERTS & NOTIFICATIONS
    %% ═══════════════════════════════════════════════════
    AlertRule ||--o{ AlertHistory : "triggers"
    AlertRule ||--o{ AlertSubscription : "has subscribers"
    AlertRule ||--o{ AlertAggregate : "aggregates"
    AlertRule }o--o{ NotificationChannel : "sends to"
    User ||--o{ AlertRule : "owns"

    NotificationChannel ||--o{ NotificationLog : "logs"
    NotificationChannel ||--o{ UserNotificationPreference : "preferences"

    %% ═══════════════════════════════════════════════════
    %% SAFETY & EVENTS
    %% ═══════════════════════════════════════════════════
    SafetyEvent }o--|| AircraftSession : "involves"

    %% ═══════════════════════════════════════════════════
    %% CANNONBALL MODE
    %% ═══════════════════════════════════════════════════
    CannonballSession ||--o{ CannonballPattern : "detects"
    CannonballSession ||--o{ CannonballAlert : "generates"
    CannonballKnownAircraft ||--o{ CannonballSession : "triggers"

    %% ═══════════════════════════════════════════════════
    %% AVIATION DATA
    %% ═══════════════════════════════════════════════════
    CachedAirport }o--o{ CachedPirep : "reports near"
    AirspaceAdvisory }o--o{ AirspaceBoundary : "within"

πŸ“ Domain Model Groups

The database models are organized into the following domain groups:

DomainπŸ“Š TablesPurpose
✈️ Aircraft Tracking4Position tracking, sessions, airframe data
πŸ” Authentication6Users, roles, API keys, OIDC
πŸ”” Alerts4Rules, history, subscriptions, aggregates
πŸ“¨ Notifications5Channels, templates, logs, preferences
⚠️ Safety1TCAS events, emergencies
πŸ—ΊοΈ Aviation Data6Airports, NOTAMs, airspace, PIREPs
πŸŽ™οΈ Audio1Radio transmissions, transcriptions
πŸ“‘ Antenna1Performance snapshots
⭐ Engagement2Favorites, quality tracking
πŸ† Gamification9Personal records, streaks, stats
πŸš” Cannonball5LE detection, patterns, alerts

πŸ“– Model Reference

✈️ Aircraft Tracking

πŸ“ AircraftSighting - Individual position reports from ADS-B receivers

Model Card

PropertyValue
Table Nameaircraft_sightings
Primary Keyid (AutoField)
Record CountHigh volume (millions+)
Update FrequencyReal-time (~1/sec per aircraft)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
timestampπŸ“… DateTimeField❌Position report time (auto-generated)
icao_hexπŸ”€ CharField(10)❌Mode S transponder code (e.g., "A12345")
callsignπŸ”€ CharField(10)βœ…Flight callsign (e.g., "UAL123")
squawkπŸ”€ CharField(4)βœ…Transponder squawk code
latitudeπŸ”’ FloatFieldβœ…WGS84 latitude
longitudeπŸ”’ FloatFieldβœ…WGS84 longitude
altitude_baroπŸ”’ IntegerFieldβœ…Barometric altitude in feet
altitude_geomπŸ”’ IntegerFieldβœ…Geometric (GPS) altitude in feet
ground_speedπŸ”’ FloatFieldβœ…Ground speed in knots
trackπŸ”’ FloatFieldβœ…Track heading in degrees (0-360)
vertical_rateπŸ”’ IntegerFieldβœ…Vertical rate in ft/min
distance_nmπŸ”’ FloatFieldβœ…Distance from receiver in nautical miles
rssiπŸ”’ FloatFieldβœ…Received signal strength indicator (dBm)
categoryπŸ”€ CharField(4)βœ…ADS-B emitter category
aircraft_typeπŸ”€ CharField(10)βœ…ICAO aircraft type designator
is_militaryβœ“ BooleanField❌Military aircraft flag
is_emergencyβœ“ BooleanField❌Emergency squawk active
sourceπŸ”€ CharField(10)❌Data source (default: "1090")

Indexes

graph LR
    subgraph "Index Strategy"
        A["idx_sightings_icao_time"] --> B["(icao_hex, timestamp)"]
        C["idx_sighting_timestamp_desc"] --> D["timestamp DESC"]
        E["idx_sighting_distance"] --> F["distance_nm WHERE NOT NULL"]
        G["idx_sighting_military"] --> H["is_military WHERE TRUE"]
        I["idx_sighting_rssi"] --> J["rssi WHERE NOT NULL"]
    end
Index NameColumnsType
idx_sightings_icao_time(icao_hex, timestamp)Composite
idx_sighting_timestamp_desctimestamp DESCDescending (PostgreSQL)
idx_sighting_distancedistance_nmPartial (WHERE NOT NULL)
idx_sighting_icao_timestamp(icao_hex, timestamp DESC)Composite
idx_sighting_militaryis_militaryPartial (WHERE TRUE)
idx_sighting_rssirssiPartial (WHERE NOT NULL)
idx_sighting_tracktrackPartial (WHERE NOT NULL)

πŸ“‹ AircraftSession - Continuous tracking session for an aircraft within range

Model Card

PropertyValue
Table Nameaircraft_sessions
Primary Keyid (AutoField)
Record CountMedium volume (thousands/day)
Update FrequencyOn position update

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
icao_hexπŸ”€ CharField(10)❌Mode S transponder code
callsignπŸ”€ CharField(10)βœ…Last seen callsign
first_seenπŸ“… DateTimeField❌Session start time
last_seenπŸ“… DateTimeField❌Last position update
total_positionsπŸ”’ IntegerField❌Position count in session
min_altitudeπŸ”’ IntegerFieldβœ…Minimum altitude observed
max_altitudeπŸ”’ IntegerFieldβœ…Maximum altitude observed
min_distance_nmπŸ”’ FloatFieldβœ…Closest approach
max_distance_nmπŸ”’ FloatFieldβœ…Maximum distance
max_vertical_rateπŸ”’ IntegerFieldβœ…Maximum vertical rate
min_rssiπŸ”’ FloatFieldβœ…Weakest signal
max_rssiπŸ”’ FloatFieldβœ…Strongest signal
is_militaryβœ“ BooleanField❌Military aircraft flag
categoryπŸ”€ CharField(4)βœ…ADS-B emitter category
aircraft_typeπŸ”€ CharField(10)βœ…ICAO aircraft type

Indexes

Index NameColumnsType
idx_sessions_last_seen_icao(last_seen, icao_hex)Composite
idx_session_last_seenlast_seen DESCDescending
idx_session_icao_lastseen(icao_hex, last_seen DESC)Composite

πŸ›©οΈ AircraftInfo - Cached aircraft information including registration, operator, and photos

Model Card

PropertyValue
Table Nameaircraft_info
Primary Keyid (AutoField)
Unique Constrainticao_hex
Record CountTens of thousands

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
icao_hexπŸ”€ CharField(10)❌Mode S transponder code (unique)
registrationπŸ”€ CharField(20)βœ…Aircraft registration (e.g., "N12345")
sourceπŸ”€ CharField(50)βœ…Data source
type_codeπŸ”€ CharField(10)βœ…ICAO type designator
type_nameπŸ”€ CharField(100)βœ…Full aircraft type name
manufacturerπŸ”€ CharField(100)βœ…Aircraft manufacturer
modelπŸ”€ CharField(100)βœ…Aircraft model
serial_numberπŸ”€ CharField(50)βœ…Manufacturer serial number
year_builtπŸ”’ IntegerFieldβœ…Year of manufacture
first_flight_dateπŸ”€ CharField(20)βœ…First flight date
delivery_dateπŸ”€ CharField(20)βœ…Delivery date
airframe_hoursπŸ”’ IntegerFieldβœ…Total airframe hours
operatorπŸ”€ CharField(100)βœ…Current operator name
operator_icaoπŸ”€ CharField(4)βœ…Operator ICAO code
operator_callsignπŸ”€ CharField(20)βœ…Operator radio callsign
ownerπŸ”€ CharField(200)βœ…Registered owner
cityπŸ”€ CharField(100)βœ…Registration city
stateπŸ”€ CharField(10)βœ…Registration state
is_interestingβœ“ BooleanField❌Interesting aircraft flag
is_piaβœ“ BooleanField❌Privacy ICAO Address
is_laddβœ“ BooleanField❌Limiting Aircraft Data Displayed
countryπŸ”€ CharField(100)βœ…Registration country
country_codeπŸ”€ CharField(3)βœ…ISO country code
categoryπŸ”€ CharField(20)βœ…Aircraft category
is_militaryβœ“ BooleanField❌Military aircraft flag
photo_urlπŸ”€ CharField(500)βœ…Full-size photo URL
photo_thumbnail_urlπŸ”€ CharField(500)βœ…Thumbnail URL
photo_photographerπŸ”€ CharField(100)βœ…Photographer name
photo_sourceπŸ”€ CharField(50)βœ…Photo source
photo_page_linkπŸ”€ CharField(500)βœ…Photo page link
photo_local_pathπŸ”€ CharField(500)βœ…Local cached photo path
photo_thumbnail_local_pathπŸ”€ CharField(500)βœ…Local thumbnail path
extra_dataπŸ“¦ JSONFieldβœ…Additional data as JSON
created_atπŸ“… DateTimeField❌Record creation time
updated_atπŸ“… DateTimeField❌Last update time
fetch_failedβœ“ BooleanField❌Data fetch failed flag

Indexes

Index NameColumnsType
idx_aircraft_info_regregistrationSingle
idx_aircraft_info_operatoroperator_icaoSingle

πŸ“‚ AirframeSourceData - Raw airframe data from each data source preserved separately

Model Card

PropertyValue
Table Nameairframe_source_data
Primary Keyid (AutoField)
Unique Constraint(aircraft_info, source)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
aircraft_info_idπŸ”— ForeignKey❌Reference to AircraftInfo
sourceπŸ”€ CharField(20)❌Data source identifier
raw_dataπŸ“¦ JSONField❌Complete raw data as JSON
registrationπŸ”€ CharField(20)βœ…Extracted registration
type_codeπŸ”€ CharField(10)βœ…Extracted type code
type_nameπŸ”€ CharField(100)βœ…Extracted type name
manufacturerπŸ”€ CharField(100)βœ…Extracted manufacturer
modelπŸ”€ CharField(100)βœ…Extracted model
serial_numberπŸ”€ CharField(50)βœ…Extracted serial number
year_builtπŸ”’ IntegerFieldβœ…Extracted year
operatorπŸ”€ CharField(100)βœ…Extracted operator
operator_icaoπŸ”€ CharField(4)βœ…Extracted operator ICAO
ownerπŸ”€ CharField(200)βœ…Extracted owner
countryπŸ”€ CharField(100)βœ…Extracted country
cityπŸ”€ CharField(100)βœ…Extracted city
stateπŸ”€ CharField(10)βœ…Extracted state
categoryπŸ”€ CharField(20)βœ…Extracted category
is_militaryβœ“ BooleanField❌Military flag
is_interestingβœ“ BooleanField❌Interesting flag
is_piaβœ“ BooleanField❌PIA flag
is_laddβœ“ BooleanField❌LADD flag
fetched_atπŸ“… DateTimeField❌Data fetch time
updated_atπŸ“… DateTimeField❌Last update time

Source Choices

SourceDescription
faaFAA Registry
adsbxADS-B Exchange
tar1090tar1090-db
openskyOpenSky Network
hexdbHexDB API
adsbloladsb.lol API
planespottersPlanespotters API

πŸ” Authentication & Authorization

πŸ‘€ SkyspyUser - Extended user profile with OIDC integration and preferences

Model Card

PropertyValue
Table Nameskyspy_users
Primary Keyid (AutoField)
RelationOneToOne with Django User

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
user_idπŸ”— OneToOneField❌Reference to Django User
auth_providerπŸ”€ CharField(20)❌Authentication provider (local/oidc)
oidc_subjectπŸ”€ CharField(255)βœ…OIDC subject identifier (unique)
oidc_issuerπŸ”€ CharField(500)βœ…OIDC issuer URL
oidc_claimsπŸ“¦ JSONFieldβœ…Cached OIDC claims
display_nameπŸ”€ CharField(100)βœ…Display name
avatar_urlπŸ”— URLFieldβœ…Avatar URL
last_activeπŸ“… DateTimeFieldβœ…Last activity timestamp
last_login_ip🌐 GenericIPAddressFieldβœ…Last login IP
preferencesπŸ“¦ JSONField❌User preferences JSON
created_atπŸ“… DateTimeField❌Creation timestamp
updated_atπŸ“… DateTimeField❌Last update

🎭 Role - Custom role with permission arrays

Model Card

PropertyValue
Table Nameroles
Primary Keyid (AutoField)
Unique Constraintname

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
nameπŸ”€ CharField(50)❌Role name (unique)
display_nameπŸ”€ CharField(100)❌Display name
descriptionπŸ“ TextFieldβœ…Role description
permissionsπŸ“¦ JSONField❌Permission array
is_systemβœ“ BooleanField❌System role flag
priorityπŸ”’ IntegerField❌Display priority
created_atπŸ“… DateTimeField❌Creation timestamp
updated_atπŸ“… DateTimeField❌Last update

Default Roles

RolePriorityDescription
πŸ‘οΈ viewer10Read-only access
βš™οΈ operator20Create/manage own alerts
πŸ“Š analyst30Export and transcription access
πŸ”§ admin40Full feature access
πŸ‘‘ superadmin100All permissions

πŸ”— UserRole - User-to-role assignment with optional expiration

Model Card

PropertyValue
Table Nameuser_roles
Primary Keyid (AutoField)
Unique Constraint(user, role)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
user_idπŸ”— ForeignKey❌Reference to User
role_idπŸ”— ForeignKey❌Reference to Role
expires_atπŸ“… DateTimeFieldβœ…Expiration time
assigned_by_idπŸ”— ForeignKeyβœ…Assigning user
created_atπŸ“… DateTimeField❌Assignment time

Indexes

Index NameColumns
idx_user_role_expiry(user, expires_at)

πŸ”‘ APIKey - Programmatic access keys with scope restrictions

Model Card

PropertyValue
Table Nameapi_keys
Primary Keyid (AutoField)
Unique Constraintkey_hash

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
user_idπŸ”— ForeignKey❌Reference to User
nameπŸ”€ CharField(100)❌Key name
key_hashπŸ”€ CharField(64)❌SHA-256 hash (unique)
key_prefixπŸ”€ CharField(16)❌First 10 characters
scopesπŸ“¦ JSONField❌Permission scopes
is_activeβœ“ BooleanField❌Active status
expires_atπŸ“… DateTimeFieldβœ…Expiration time
last_used_atπŸ“… DateTimeFieldβœ…Last usage time
last_used_ip🌐 GenericIPAddressFieldβœ…Last usage IP
created_atπŸ“… DateTimeField❌Creation time

πŸšͺ FeatureAccess - Per-feature public/private access configuration

Model Card

PropertyValue
Table Namefeature_access
Primary Keyfeature (CharField)

Fields

FieldTypeβšͺ NullDescription
featureπŸ”€ CharField(30)❌Feature ID (primary key)
read_accessπŸ”€ CharField(20)❌Read access level
write_accessπŸ”€ CharField(20)❌Write access level
is_enabledβœ“ BooleanField❌Feature enabled flag
settingsπŸ“¦ JSONField❌Feature-specific settings
updated_atπŸ“… DateTimeField❌Last update
updated_by_idπŸ”— ForeignKeyβœ…Last updater

Access Levels

LevelDescription
🌍 publicNo authentication required
πŸ”“ authenticatedAny logged-in user
πŸ”’ permissionSpecific permission required

πŸ—ΊοΈ OIDCClaimMapping - Map OIDC claims to roles for automatic role assignment

Model Card

PropertyValue
Table Nameoidc_claim_mappings
Primary Keyid (AutoField)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
nameπŸ”€ CharField(100)❌Mapping name
claim_nameπŸ”€ CharField(100)❌OIDC claim name
match_typeπŸ”€ CharField(20)❌Match type (exact/contains/regex)
claim_valueπŸ”€ CharField(255)❌Value to match
role_idπŸ”— ForeignKey❌Role to assign
priorityπŸ”’ IntegerField❌Processing priority
is_activeβœ“ BooleanField❌Active status
created_atπŸ“… DateTimeField❌Creation time
updated_atπŸ“… DateTimeField❌Last update

πŸ”” Alerts & Notifications

πŸ“œ AlertRule - User-defined alert rules with complex conditions

Model Card

PropertyValue
Table Namealert_rules
Primary Keyid (AutoField)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
nameπŸ”€ CharField(100)❌Rule name
rule_typeπŸ”€ CharField(30)βœ…Rule type identifier
operatorπŸ”€ CharField(10)❌Comparison operator
valueπŸ”€ CharField(100)βœ…Comparison value
conditionsπŸ“¦ JSONFieldβœ…Complex AND/OR conditions
descriptionπŸ”€ CharField(200)βœ…Rule description
enabledβœ“ BooleanField❌Enabled status
priorityπŸ”€ CharField(20)❌Priority level
starts_atπŸ“… DateTimeFieldβœ…Start time
expires_atπŸ“… DateTimeFieldβœ…Expiration time
api_urlπŸ”€ CharField(500)βœ…Webhook URL
cooldown_minutesπŸ”’ IntegerField❌Cooldown period
last_triggeredπŸ“… DateTimeFieldβœ…Last trigger time
use_global_notificationsβœ“ BooleanField❌Use global config
owner_idπŸ”— ForeignKeyβœ…Rule owner
visibilityπŸ”€ CharField(20)❌Visibility level
is_systemβœ“ BooleanField❌System rule flag
is_sharedβœ“ BooleanField❌Legacy shared flag
suppression_windowsπŸ“¦ JSONField❌Suppression windows
created_atπŸ“… DateTimeField❌Creation time
updated_atπŸ“… DateTimeField❌Last update

Operator Choices

OperatorSymbolDescription
eq=Equals
neq!=Not Equals
lt\<Less Than
le\<=Less Than or Equal
gt\>Greater Than
ge\>=Greater Than or Equal
contains*...*Contains
startswith^...Starts With
endswith...$Ends With
regex/.../Regex Match

Indexes

Index NameColumns
idx_alert_rules_type(rule_type, enabled)
idx_alert_rules_vis(visibility, enabled)
idx_alert_rules_owner(owner, enabled)

πŸ“Š AlertHistory - History of triggered alerts

Model Card

PropertyValue
Table Namealert_history
Primary Keyid (AutoField)
VolumeHigh (depends on rule count)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
rule_idπŸ”— ForeignKeyβœ…Reference to AlertRule
rule_nameπŸ”€ CharField(100)βœ…Rule name at trigger time
icao_hexπŸ”€ CharField(10)βœ…Triggering aircraft
callsignπŸ”€ CharField(10)βœ…Aircraft callsign
messageπŸ“ TextFieldβœ…Alert message
priorityπŸ”€ CharField(20)βœ…Alert priority
aircraft_dataπŸ“¦ JSONFieldβœ…Aircraft snapshot
triggered_atπŸ“… DateTimeField❌Trigger timestamp
user_idπŸ”— ForeignKeyβœ…Rule owner
session_keyπŸ”€ CharField(40)βœ…Anonymous session key
acknowledgedβœ“ BooleanField❌Acknowledged status
acknowledged_by_idπŸ”— ForeignKeyβœ…Acknowledging user
acknowledged_atπŸ“… DateTimeFieldβœ…Acknowledgment time

Indexes

Index NameColumns
idx_alert_hist_user(user, triggered_at)
idx_alert_hist_ack(acknowledged, triggered_at)
idx_alert_history_triggeredtriggered_at DESC

πŸ“¬ AlertSubscription - User subscriptions to shared/public alert rules

Model Card

PropertyValue
Table Namealert_subscriptions
Unique Constraints(user, rule), (session_key, rule)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
user_idπŸ”— ForeignKeyβœ…Subscribing user
session_keyπŸ”€ CharField(40)βœ…Anonymous session key
rule_idπŸ”— ForeignKey❌Subscribed rule
notify_on_triggerβœ“ BooleanField❌Notification enabled
created_atπŸ“… DateTimeField❌Subscription time

πŸ“ˆ AlertAggregate - Aggregated alert statistics for time windows

Model Card

PropertyValue
Table Namealert_aggregates
Primary Keyid (AutoField)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
rule_idπŸ”— ForeignKey❌Reference to AlertRule
window_startπŸ“… DateTimeField❌Window start time
window_endπŸ“… DateTimeField❌Window end time
trigger_countπŸ”’ IntegerField❌Number of triggers
unique_aircraftπŸ”’ IntegerField❌Unique aircraft count
sample_aircraftπŸ“¦ JSONField❌Sample aircraft list

πŸ“¨ Notification System

βš™οΈ NotificationConfig - Singleton notification configuration

Model Card

PropertyValue
Table Namenotification_config
Primary Keyid (always 1)
PatternSingleton

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key (always 1)
apprise_urlsπŸ“ TextField❌Apprise URL configuration
cooldown_secondsπŸ”’ IntegerField❌Default cooldown
enabledβœ“ BooleanField❌Global enabled flag
updated_atπŸ“… DateTimeField❌Last update

πŸ“‘ NotificationChannel - Reusable notification channel definitions

Model Card

PropertyValue
Table Namenotification_channels
Primary Keyid (AutoField)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
nameπŸ”€ CharField(100)❌Channel name
channel_typeπŸ”€ CharField(30)❌Channel type
apprise_urlπŸ“ TextField❌Apprise URL
descriptionπŸ”€ CharField(200)βœ…Description
supports_richβœ“ BooleanField❌Rich formatting support
is_globalβœ“ BooleanField❌Global availability
owner_idπŸ”— ForeignKeyβœ…Channel owner
enabledβœ“ BooleanField❌Enabled status
verifiedβœ“ BooleanField❌Verified status
last_successπŸ“… DateTimeFieldβœ…Last success time
last_failureπŸ“… DateTimeFieldβœ…Last failure time
last_errorπŸ“ TextFieldβœ…Last error message
created_atπŸ“… DateTimeField❌Creation time
updated_atπŸ“… DateTimeField❌Last update

Channel Types

TypeIconDescription
discordπŸ’¬Discord
slackπŸ“±Slack
pushoverπŸ“²Pushover
telegram✈️Telegram
emailπŸ“§Email
webhookπŸ”—Generic Webhook
ntfyπŸ””ntfy
gotifyπŸ“£Gotify
home_assistant🏠Home Assistant
twilioπŸ“žTwilio SMS
customπŸ”§Custom Apprise URL

πŸ“ NotificationTemplate - Message templates with variable substitution

Model Card

PropertyValue
Table Namenotification_templates
Unique Constraintname

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
nameπŸ”€ CharField(100)❌Template name (unique)
descriptionπŸ”€ CharField(200)βœ…Description
title_templateπŸ”€ CharField(200)❌Title template
body_templateπŸ“ TextField❌Body template
discord_embedπŸ“¦ JSONFieldβœ…Discord embed JSON
slack_blocksπŸ“¦ JSONFieldβœ…Slack Block Kit JSON
event_typeπŸ”€ CharField(30)βœ…Matching event type
priorityπŸ”€ CharField(20)βœ…Matching priority
is_defaultβœ“ BooleanField❌Default template flag
created_atπŸ“… DateTimeField❌Creation time
updated_atπŸ“… DateTimeField❌Last update

πŸ“‹ NotificationLog - Log of sent notifications with retry tracking

Model Card

PropertyValue
Table Namenotification_logs
Primary Keyid (AutoField)
VolumeHigh

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
timestampπŸ“… DateTimeField❌Log timestamp
notification_typeπŸ”€ CharField(50)βœ…Notification type
icao_hexπŸ”€ CharField(10)βœ…Aircraft ICAO
callsignπŸ”€ CharField(10)βœ…Aircraft callsign
messageπŸ“ TextFieldβœ…Notification message
detailsπŸ“¦ JSONFieldβœ…Additional details
channel_idπŸ”— ForeignKeyβœ…Channel reference
channel_urlπŸ“ TextFieldβœ…Actual URL used
statusπŸ”€ CharField(20)❌Status (pending/sent/failed/retrying)
retry_countπŸ”’ IntegerField❌Retry attempt count
max_retriesπŸ”’ IntegerField❌Maximum retries
next_retry_atπŸ“… DateTimeFieldβœ…Next retry time
last_errorπŸ“ TextFieldβœ…Last error message
sent_atπŸ“… DateTimeFieldβœ…Send time
duration_msπŸ”’ IntegerFieldβœ…Send duration

πŸ”• UserNotificationPreference - Per-user notification preferences

Model Card

PropertyValue
Table Nameuser_notification_preferences
Unique Constraint(user, channel)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
user_idπŸ”— ForeignKey❌User reference
channel_idπŸ”— ForeignKey❌Channel reference
min_priorityπŸ”€ CharField(20)❌Minimum priority
event_typesπŸ“¦ JSONField❌Event type filter
quiet_hours_start⏰ TimeFieldβœ…Quiet hours start
quiet_hours_end⏰ TimeFieldβœ…Quiet hours end
critical_overrides_quietβœ“ BooleanField❌Critical override flag
timezoneπŸ”€ CharField(50)❌User timezone
enabledβœ“ BooleanField❌Enabled status
created_atπŸ“… DateTimeField❌Creation time
updated_atπŸ“… DateTimeField❌Last update

⚠️ Safety Events

🚨 SafetyEvent - TCAS conflicts and dangerous flight parameters

Model Card

PropertyValue
Table Namesafety_events
Primary Keyid (AutoField)
CriticalityHigh

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
timestampπŸ“… DateTimeField❌Event timestamp
event_typeπŸ”€ CharField(50)❌Event type
severityπŸ”€ CharField(20)❌Severity level
icao_hexπŸ”€ CharField(10)❌Primary aircraft
icao_hex_2πŸ”€ CharField(10)βœ…Secondary aircraft
callsignπŸ”€ CharField(10)βœ…Primary callsign
callsign_2πŸ”€ CharField(10)βœ…Secondary callsign
messageπŸ“ TextFieldβœ…Event message
detailsπŸ“¦ JSONFieldβœ…Event details
aircraft_snapshotπŸ“¦ JSONFieldβœ…Primary telemetry snapshot
aircraft_snapshot_2πŸ“¦ JSONFieldβœ…Secondary telemetry snapshot
acknowledgedβœ“ BooleanField❌Acknowledged status
acknowledged_atπŸ“… DateTimeFieldβœ…Acknowledgment time

Event Types

TypeSeverityDescription
tcas_raπŸ”΄ CriticalTCAS Resolution Advisory
tcas_ta🟠 HighTCAS Traffic Advisory
extreme_vs🟠 HighExtreme Vertical Speed
vs_reversal🟑 MediumVertical Speed Reversal
proximity_conflictπŸ”΄ CriticalProximity Conflict
emergency_squawkπŸ”΄ CriticalEmergency Squawk
7500πŸ”΄ CriticalSquawk 7500 (Hijack)
7600🟠 HighSquawk 7600 (Radio Failure)
7700πŸ”΄ CriticalSquawk 7700 (Emergency)

Indexes

Index NameColumns
idx_safety_events_type_time(event_type, timestamp)
idx_safety_event_timestamptimestamp DESC

πŸ—ΊοΈ Aviation Data

πŸ›« CachedAirport - Cached airport data from Aviation Weather Center

Model Card

PropertyValue
Table Namecached_airports
Unique Constrainticao_id
Refresh Rate30 days

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
fetched_atπŸ“… DateTimeField❌Fetch timestamp
icao_idπŸ”€ CharField(4)❌ICAO identifier (unique)
nameπŸ”€ CharField(200)βœ…Airport name
latitudeπŸ”’ FloatField❌WGS84 latitude
longitudeπŸ”’ FloatField❌WGS84 longitude
elevation_ftπŸ”’ IntegerFieldβœ…Field elevation
airport_typeπŸ”€ CharField(50)βœ…Airport type
countryπŸ”€ CharField(100)βœ…Country name
regionπŸ”€ CharField(100)βœ…Region/state
source_dataπŸ“¦ JSONFieldβœ…Raw API response

πŸ“‘ CachedNavaid - Cached navigation aid data

Model Card

PropertyValue
Table Namecached_navaids
Primary Keyid (AutoField)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
fetched_atπŸ“… DateTimeField❌Fetch timestamp
identπŸ”€ CharField(10)❌Navaid identifier
nameπŸ”€ CharField(100)βœ…Navaid name
navaid_typeπŸ”€ CharField(20)βœ…Type (VOR, NDB, etc.)
latitudeπŸ”’ FloatField❌WGS84 latitude
longitudeπŸ”’ FloatField❌WGS84 longitude
frequencyπŸ”’ FloatFieldβœ…Frequency (MHz/kHz)
channelπŸ”€ CharField(10)βœ…TACAN channel
source_dataπŸ“¦ JSONFieldβœ…Raw API response

πŸ“‹ CachedNotam - Cached NOTAM and TFR data

Model Card

PropertyValue
Table Namecached_notams
Unique Constraintnotam_id
Archive SupportYes

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
notam_idπŸ”€ CharField(50)❌NOTAM identifier (unique)
notam_typeπŸ”€ CharField(10)❌NOTAM type
classificationπŸ”€ CharField(20)βœ…Classification
locationπŸ”€ CharField(10)❌ICAO location
latitudeπŸ”’ FloatFieldβœ…Center latitude
longitudeπŸ”’ FloatFieldβœ…Center longitude
radius_nmπŸ”’ FloatFieldβœ…TFR radius
floor_ftπŸ”’ IntegerFieldβœ…Floor altitude
ceiling_ftπŸ”’ IntegerFieldβœ…Ceiling altitude
effective_startπŸ“… DateTimeField❌Start time
effective_endπŸ“… DateTimeFieldβœ…End time
is_permanentβœ“ BooleanField❌Permanent flag
textπŸ“ TextField❌NOTAM text
raw_textπŸ“ TextFieldβœ…Raw NOTAM text
keywordsπŸ“¦ JSONFieldβœ…Extracted keywords
geometryπŸ“¦ JSONFieldβœ…TFR GeoJSON boundary
reasonπŸ”€ CharField(200)βœ…TFR reason
source_dataπŸ“¦ JSONFieldβœ…Raw API response
fetched_atπŸ“… DateTimeField❌Fetch timestamp
created_atπŸ“… DateTimeField❌Creation time
is_archivedβœ“ BooleanField❌Archived status
archived_atπŸ“… DateTimeFieldβœ…Archive time
archive_reasonπŸ”€ CharField(50)βœ…Archive reason

Indexes

Index NameColumns
idx_notam_loc_start(location, effective_start)
idx_notam_type_start(notam_type, effective_start)
idx_notam_location(latitude, longitude)
idx_notam_validity(effective_end, effective_start)
idx_notam_archive(is_archived, archived_at)

🌀️ AirspaceAdvisory - Active airspace advisories (G-AIRMETs, SIGMETs)

Model Card

PropertyValue
Table Nameairspace_advisories
Primary Keyid (AutoField)
Refresh RateHourly

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
fetched_atπŸ“… DateTimeField❌Fetch timestamp
advisory_idπŸ”€ CharField(50)❌Advisory identifier
advisory_typeπŸ”€ CharField(20)❌Advisory type
hazardπŸ”€ CharField(20)βœ…Hazard type
severityπŸ”€ CharField(20)βœ…Severity level
valid_fromπŸ“… DateTimeFieldβœ…Valid from time
valid_toπŸ“… DateTimeFieldβœ…Valid to time
lower_alt_ftπŸ”’ IntegerFieldβœ…Lower altitude
upper_alt_ftπŸ”’ IntegerFieldβœ…Upper altitude
regionπŸ”€ CharField(20)βœ…Geographic region
polygonπŸ“¦ JSONFieldβœ…GeoJSON polygon
raw_textπŸ“ TextFieldβœ…Raw advisory text
source_dataπŸ“¦ JSONFieldβœ…Raw API response

πŸ”² AirspaceBoundary - Static airspace boundary data (Class B/C/D, MOAs)

Model Card

PropertyValue
Table Nameairspace_boundaries
Primary Keyid (AutoField)
Update FrequencyMonthly

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
fetched_atπŸ“… DateTimeField❌Fetch timestamp
nameπŸ”€ CharField(100)❌Airspace name
icaoπŸ”€ CharField(4)βœ…Associated airport
airspace_classπŸ”€ CharField(20)❌Airspace class
floor_ftπŸ”’ IntegerField❌Floor altitude
ceiling_ftπŸ”’ IntegerField❌Ceiling altitude
center_latπŸ”’ FloatField❌Center latitude
center_lonπŸ”’ FloatField❌Center longitude
radius_nmπŸ”’ FloatFieldβœ…Radius (circular)
polygonπŸ“¦ JSONFieldβœ…GeoJSON polygon
controlling_agencyπŸ”€ CharField(100)βœ…Controlling agency
scheduleπŸ”€ CharField(200)βœ…Operating schedule
sourceπŸ”€ CharField(50)❌Data source
source_idπŸ”€ CharField(100)βœ…External ID
updated_atπŸ“… DateTimeField❌Last update

✈️ CachedPirep - Cached Pilot Reports (PIREPs)

Model Card

PropertyValue
Table Namecached_pireps
Unique Constraintpirep_id
Retention24 hours

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
fetched_atπŸ“… DateTimeField❌Fetch timestamp
pirep_idπŸ”€ CharField(100)❌PIREP identifier (unique)
report_typeπŸ”€ CharField(10)❌Report type (UA/UUA)
latitudeπŸ”’ FloatFieldβœ…Location latitude
longitudeπŸ”’ FloatFieldβœ…Location longitude
locationπŸ”€ CharField(50)βœ…Location string
observation_timeπŸ“… DateTimeFieldβœ…Observation time
flight_levelπŸ”’ IntegerFieldβœ…Flight level
altitude_ftπŸ”’ IntegerFieldβœ…Altitude in feet
aircraft_typeπŸ”€ CharField(10)βœ…Reporting aircraft type
turbulence_typeπŸ”€ CharField(20)βœ…Turbulence intensity
turbulence_freqπŸ”€ CharField(20)βœ…Turbulence frequency
turbulence_base_ftπŸ”’ IntegerFieldβœ…Turbulence base
turbulence_top_ftπŸ”’ IntegerFieldβœ…Turbulence top
icing_typeπŸ”€ CharField(20)βœ…Icing intensity
icing_intensityπŸ”€ CharField(20)βœ…Icing type
icing_base_ftπŸ”’ IntegerFieldβœ…Icing base
icing_top_ftπŸ”’ IntegerFieldβœ…Icing top
sky_coverπŸ”€ CharField(100)βœ…Sky condition
visibility_smπŸ”’ FloatFieldβœ…Visibility (SM)
weatherπŸ”€ CharField(100)βœ…Weather phenomena
temperature_cπŸ”’ IntegerFieldβœ…Temperature
wind_dirπŸ”’ IntegerFieldβœ…Wind direction
wind_speed_ktπŸ”’ IntegerFieldβœ…Wind speed
raw_textπŸ“ TextFieldβœ…Raw PIREP text
source_dataπŸ“¦ JSONFieldβœ…Raw API response
is_archivedβœ“ BooleanField❌Archived status
archived_atπŸ“… DateTimeFieldβœ…Archive time
archive_reasonπŸ”€ CharField(50)βœ…Archive reason

πŸŽ™οΈ Audio Transmissions

πŸ”Š AudioTransmission - Audio transmissions captured for transcription

Model Card

PropertyValue
Table Nameaudio_transmissions
Primary Keyid (AutoField)
StorageS3/Local

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
created_atπŸ“… DateTimeField❌Creation timestamp
filenameπŸ”€ CharField(255)❌Audio filename
s3_keyπŸ”€ CharField(500)βœ…S3 object key
s3_urlπŸ”€ CharField(500)βœ…S3 URL
file_size_bytesπŸ”’ IntegerFieldβœ…File size
duration_secondsπŸ”’ FloatFieldβœ…Audio duration
formatπŸ”€ CharField(10)❌Audio format
frequency_mhzπŸ”’ FloatFieldβœ…Radio frequency
channel_nameπŸ”€ CharField(100)βœ…Channel name
squelch_levelπŸ”’ FloatFieldβœ…Squelch level
transcription_statusπŸ”€ CharField(20)❌Transcription status
transcription_queued_atπŸ“… DateTimeFieldβœ…Queue time
transcription_started_atπŸ“… DateTimeFieldβœ…Start time
transcription_completed_atπŸ“… DateTimeFieldβœ…Completion time
transcription_errorπŸ“ TextFieldβœ…Error message
transcriptπŸ“ TextFieldβœ…Transcription text
transcript_confidenceπŸ”’ FloatFieldβœ…Confidence score
transcript_languageπŸ”€ CharField(10)βœ…Detected language
transcript_segmentsπŸ“¦ JSONFieldβœ…Word-level timestamps
identified_airframesπŸ“¦ JSONFieldβœ…Identified aircraft
extra_metadataπŸ“¦ JSONFieldβœ…Additional metadata

πŸ“‘ Antenna Analytics

πŸ“Š AntennaAnalyticsSnapshot - Periodic antenna performance snapshots

Model Card

PropertyValue
Table Nameantenna_analytics_snapshots
Primary Keyid (AutoField)
Snapshot Typesscheduled, hourly, daily

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
timestampπŸ“… DateTimeField❌Snapshot timestamp
snapshot_typeπŸ”€ CharField(20)❌Type (scheduled/hourly/daily)
window_hoursπŸ”’ FloatField❌Time window size
max_range_nmπŸ”’ FloatFieldβœ…Maximum range
avg_range_nmπŸ”’ FloatFieldβœ…Average range
min_range_nmπŸ”’ FloatFieldβœ…Minimum range
range_p50_nmπŸ”’ FloatFieldβœ…50th percentile range
range_p75_nmπŸ”’ FloatFieldβœ…75th percentile range
range_p90_nmπŸ”’ FloatFieldβœ…90th percentile range
range_p95_nmπŸ”’ FloatFieldβœ…95th percentile range
best_rssiπŸ”’ FloatFieldβœ…Best signal strength
avg_rssiπŸ”’ FloatFieldβœ…Average signal strength
worst_rssiπŸ”’ FloatFieldβœ…Worst signal strength
total_positionsπŸ”’ IntegerField❌Total position count
unique_aircraftπŸ”’ IntegerField❌Unique aircraft count
positions_per_hourπŸ”’ FloatField❌Position rate
range_by_directionπŸ“¦ JSONField❌Directional range data
sectors_with_dataπŸ”’ IntegerField❌Sectors with data (0-12)
coverage_percentageπŸ”’ FloatField❌Coverage percentage
estimated_gain_dbπŸ”’ FloatFieldβœ…Estimated antenna gain
performance_scoreπŸ”’ FloatFieldβœ…Performance score (0-100)

⭐ Engagement Tracking

❀️ AircraftFavorite - User-favorited aircraft tracking

Model Card

PropertyValue
Table Nameaircraft_favorites
Unique Constraints(user, icao_hex), (session_key, icao_hex)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
user_idπŸ”— ForeignKeyβœ…User reference
session_keyπŸ”€ CharField(40)βœ…Anonymous session
icao_hexπŸ”€ CharField(10)❌Aircraft ICAO
registrationπŸ”€ CharField(20)βœ…Registration
callsignπŸ”€ CharField(10)βœ…Last callsign
notesπŸ“ TextFieldβœ…User notes
times_seenπŸ”’ IntegerField❌Times seen while favorited
last_seen_atπŸ“… DateTimeFieldβœ…Last seen time
total_tracking_minutesπŸ”’ FloatField❌Total tracking time
notify_on_detectionβœ“ BooleanField❌Notification enabled
created_atπŸ“… DateTimeField❌Creation time
updated_atπŸ“… DateTimeField❌Last update

πŸ“Ά SessionTrackingQuality - Extended session quality metrics

Model Card

PropertyValue
Table Namesession_tracking_quality
RelationOneToOne with AircraftSession

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
session_idπŸ”— OneToOneField❌Session reference
expected_positionsπŸ”’ IntegerField❌Expected positions
actual_positionsπŸ”’ IntegerField❌Actual positions
completeness_scoreπŸ”’ FloatField❌Completeness (0-100)
avg_update_rateπŸ”’ FloatField❌Positions per minute
total_gapsπŸ”’ IntegerField❌Number of gaps
max_gap_secondsπŸ”’ IntegerField❌Longest gap
avg_gap_secondsπŸ”’ FloatField❌Average gap
gap_percentageπŸ”’ FloatField❌Gap percentage
avg_rssiπŸ”’ FloatFieldβœ…Average signal
rssi_varianceπŸ”’ FloatFieldβœ…Signal variance
quality_gradeπŸ”€ CharField(20)❌Quality grade
calculated_atπŸ“… DateTimeField❌Calculation time

πŸ† Gamification & Statistics

πŸ₯‡ PersonalRecord - All-time personal bests

Model Card

PropertyValue
Table Namepersonal_records
Unique Constraintrecord_type

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
record_typeπŸ”€ CharField(50)❌Record type (unique)
icao_hexπŸ”€ CharField(10)❌Record-holding aircraft
callsignπŸ”€ CharField(10)βœ…Callsign
aircraft_typeπŸ”€ CharField(10)βœ…Aircraft type
registrationπŸ”€ CharField(20)βœ…Registration
operatorπŸ”€ CharField(100)βœ…Operator
valueπŸ”’ FloatField❌Record value
session_idπŸ”— ForeignKeyβœ…Session reference
achieved_atπŸ“… DateTimeField❌Achievement time
previous_valueπŸ”’ FloatFieldβœ…Previous record
previous_icao_hexπŸ”€ CharField(10)βœ…Previous holder
previous_achieved_atπŸ“… DateTimeFieldβœ…Previous time
created_atπŸ“… DateTimeField❌Creation time
updated_atπŸ“… DateTimeField❌Last update

Record Types

RecordIconDescription
max_distanceπŸ“Furthest Aircraft Tracked
max_altitude⬆️Highest Altitude Aircraft
max_speedπŸ’¨Fastest Aircraft Tracked
longest_session⏱️Longest Tracking Session
most_positionsπŸ“Most Positions for Single Aircraft
closest_approach🎯Closest Approach
max_vertical_rateπŸš€Fastest Climb Rate
max_descent_rateπŸ“‰Fastest Descent Rate
earliest_morningπŸŒ…Earliest Morning Sighting
latest_nightπŸŒ™Latest Night Sighting

πŸ“… DailyStats - Daily aggregated statistics

Model Card

PropertyValue
Table Namedaily_stats
Unique Constraintdate

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
dateπŸ“… DateField❌Statistics date (unique)
unique_aircraftπŸ”’ IntegerField❌Unique aircraft count
new_aircraftπŸ”’ IntegerField❌First-time sightings
total_sessionsπŸ”’ IntegerField❌Session count
total_positionsπŸ”’ IntegerField❌Position count
military_countπŸ”’ IntegerField❌Military aircraft count
max_distance_nmπŸ”’ FloatFieldβœ…Maximum distance
max_altitudeπŸ”’ IntegerFieldβœ…Maximum altitude
max_speedπŸ”’ FloatFieldβœ…Maximum speed
aircraft_typesπŸ“¦ JSONField❌Type distribution
operatorsπŸ“¦ JSONField❌Operator distribution
created_atπŸ“… DateTimeField❌Creation time
updated_atπŸ“… DateTimeField❌Last update

πŸš” Cannonball Mode

Cannonball Mode provides law enforcement aircraft detection and pattern analysis.

flowchart LR
    subgraph Detection
        A[Known Aircraft DB] --> B{Match?}
        C[Pattern Analysis] --> B
    end

    subgraph Tracking
        B --> D[Cannonball Session]
        D --> E[Pattern Detection]
        D --> F[Alert Generation]
    end

    subgraph Analysis
        E --> G[Circling]
        E --> H[Loitering]
        E --> I[Grid Search]
        E --> J[Surveillance]
    end
πŸ”„ CannonballPattern - Detected flight patterns indicating surveillance activity

Model Card

PropertyValue
Table Namecannonball_patterns
Primary Keyid (AutoField)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
icao_hexπŸ”€ CharField(10)❌Aircraft ICAO
callsignπŸ”€ CharField(10)βœ…Callsign
pattern_typeπŸ”€ CharField(30)❌Pattern type
confidenceπŸ”€ CharField(10)❌Confidence level
confidence_scoreπŸ”’ FloatField❌Confidence score (0-1)
center_latπŸ”’ FloatField❌Pattern center latitude
center_lonπŸ”’ FloatField❌Pattern center longitude
radius_nmπŸ”’ FloatFieldβœ…Pattern radius
pattern_dataπŸ“¦ JSONField❌Additional pattern data
position_samplesπŸ“¦ JSONField❌Position samples
started_atπŸ“… DateTimeField❌Pattern start time
ended_atπŸ“… DateTimeFieldβœ…Pattern end time
duration_secondsπŸ”’ IntegerField❌Duration
detected_atπŸ“… DateTimeField❌Detection timestamp
session_idπŸ”— ForeignKeyβœ…Session reference

Pattern Types

TypeIconDescription
circlingπŸ”„Circling
loitering⏸️Loitering
grid_searchπŸ”²Grid Search
speed_trapπŸš—Speed Trap
parallel_highwayπŸ›£οΈParallel to Highway
surveillanceπŸ‘οΈGeneral Surveillance
pursuitπŸƒPursuit Pattern

πŸ“‹ CannonballSession - Tracking session for potential law enforcement aircraft

Model Card

PropertyValue
Table Namecannonball_sessions
Primary Keyid (AutoField)

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
icao_hexπŸ”€ CharField(10)❌Aircraft ICAO
callsignπŸ”€ CharField(10)βœ…Callsign
registrationπŸ”€ CharField(15)βœ…Registration
identification_methodπŸ”€ CharField(20)❌How identified
identification_reasonπŸ”€ CharField(200)βœ…Identification reason
operator_nameπŸ”€ CharField(100)βœ…Operator name
operator_icaoπŸ”€ CharField(10)βœ…Operator ICAO
aircraft_typeπŸ”€ CharField(50)βœ…Aircraft type
is_activeβœ“ BooleanField❌Active status
threat_levelπŸ”€ CharField(20)❌Threat level
urgency_scoreπŸ”’ FloatField❌Urgency score (0-100)
last_latπŸ”’ FloatFieldβœ…Last latitude
last_lonπŸ”’ FloatFieldβœ…Last longitude
last_altitudeπŸ”’ IntegerFieldβœ…Last altitude
last_ground_speedπŸ”’ IntegerFieldβœ…Last ground speed
last_trackπŸ”’ IntegerFieldβœ…Last track
user_idπŸ”— ForeignKeyβœ…User reference
distance_nmπŸ”’ FloatFieldβœ…Distance from user
bearingπŸ”’ FloatFieldβœ…Bearing from user
closing_speed_ktsπŸ”’ FloatFieldβœ…Closing speed
first_seenπŸ“… DateTimeField❌Session start
last_seenπŸ“… DateTimeField❌Last update
session_duration_secondsπŸ”’ IntegerField❌Duration
pattern_countπŸ”’ IntegerField❌Pattern count
alert_countπŸ”’ IntegerField❌Alert count
position_countπŸ”’ IntegerField❌Position count
metadataπŸ“¦ JSONField❌Additional metadata

πŸ—ƒοΈ CannonballKnownAircraft - Database of known law enforcement aircraft

Model Card

PropertyValue
Table Namecannonball_known_aircraft
Unique Constrainticao_hex

Fields

FieldTypeβšͺ NullDescription
idπŸ”’ AutoField❌Primary key
icao_hexπŸ”€ CharField(10)❌Aircraft ICAO (unique)
registrationπŸ”€ CharField(15)βœ…Registration
aircraft_typeπŸ”€ CharField(50)βœ…Aircraft type
aircraft_modelπŸ”€ CharField(100)βœ…Aircraft model
agency_nameπŸ”€ CharField(200)❌Agency name
agency_typeπŸ”€ CharField(20)❌Agency type
agency_stateπŸ”€ CharField(2)βœ…US state
agency_cityπŸ”€ CharField(100)βœ…City
sourceπŸ”€ CharField(20)❌Data source
source_urlπŸ”— URLFieldβœ…Source URL
verifiedβœ“ BooleanField❌Verified status
verified_atπŸ“… DateTimeFieldβœ…Verification time
verified_by_idπŸ”— ForeignKeyβœ…Verifying user
times_detectedπŸ”’ IntegerField❌Detection count
last_detectedπŸ“… DateTimeFieldβœ…Last detection
notesπŸ“ TextFieldβœ…Notes
created_atπŸ“… DateTimeField❌Creation time
updated_atπŸ“… DateTimeField❌Last update

⚑ Performance Optimization

Index Strategy

SkySpy uses a comprehensive indexing strategy optimized for common query patterns.

graph TD
    subgraph "Query Patterns"
        A[Time-Based] --> A1["Recent sightings"]
        A --> A2["Session history"]

        B[Aircraft Lookups] --> B1["Track by ICAO"]
        B --> B2["History queries"]

        C[Filtered Queries] --> C1["Military aircraft"]
        C --> C2["Distance range"]
        C --> C3["Signal strength"]
    end

    subgraph "Index Types"
        D[Composite] --> D1["Multi-column"]
        E[Partial] --> E1["Conditional"]
        F[Descending] --> F1["Time ordering"]
    end

    A1 --> F
    A2 --> F
    B1 --> D
    B2 --> D
    C1 --> E
    C2 --> E
    C3 --> E

Tip: Partial indexes in PostgreSQL dramatically reduce index size for sparse boolean columns like is_military (typically less than 5% of traffic).

Time-Based Queries

-- Most common pattern: Recent sightings ordered by time
CREATE INDEX idx_sighting_timestamp_desc ON aircraft_sightings(timestamp DESC);
CREATE INDEX idx_session_last_seen ON aircraft_sessions(last_seen DESC);

Aircraft Lookups

-- Track history for specific aircraft
CREATE INDEX idx_sighting_icao_timestamp ON aircraft_sightings(icao_hex, timestamp DESC);
CREATE INDEX idx_session_icao_lastseen ON aircraft_sessions(icao_hex, last_seen DESC);

Partial Indexes

-- Military aircraft filtering (typically less than 5% of traffic)
CREATE INDEX idx_sighting_military ON aircraft_sightings(is_military) WHERE is_military = TRUE;

-- Distance-based queries (exclude null values)
CREATE INDEX idx_sighting_distance ON aircraft_sightings(distance_nm) WHERE distance_nm IS NOT NULL;

Query Optimization Tips

Performance Best Practices

PatternRecommendation
πŸ“… Recent sightingsUse timestamp__gte with indexed column
✈️ Aircraft historyQuery by icao_hex first, then filter by time
πŸ“ Distance filteringUse partial index, exclude nulls
πŸŽ–οΈ Military aircraftPartial index on boolean flag
πŸ“‹ Session lookupsUse composite (icao_hex, last_seen) index

Connection Pooling

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'CONN_MAX_AGE': 60,  # Reuse connections for 60 seconds
    }
}

πŸ“¦ Data Retention Policies

Active Data

TableRetentionPolicy
πŸ“ aircraft_sightings30 daysArchive older positions
πŸ“‹ aircraft_sessions90 daysKeep for history
πŸ”” alert_history90 daysArchive older alerts
πŸ“¨ notification_logs30 daysDelete after retention
⚠️ safety_events1 yearArchive for analysis

Cached Data

TableRetentionPolicy
πŸ›©οΈ aircraft_infoIndefiniteUpdate on access
πŸ›« cached_airports30 daysRefresh periodically
πŸ“‹ cached_notamsActive + 7 daysArchive expired
✈️ cached_pireps24 hoursArchive after expiry
🌀️ airspace_advisoriesActive + 24 hoursArchive expired

Archive Strategy

# Mark expired NOTAMs as archived
CachedNotam.objects.filter(
    effective_end__lt=timezone.now() - timedelta(days=7),
    is_archived=False
).update(
    is_archived=True,
    archived_at=timezone.now(),
    archive_reason='expired'
)

πŸ”„ Migration Strategy

Running Migrations

# Apply all pending migrations
python manage.py migrate

# Show migration status
python manage.py showmigrations

# Create new migration
python manage.py makemigrations skyspy

Migration Best Practices

Important Guidelines

  1. Never edit applied migrations - Create new migrations for changes
  2. Use atomic=False for index creation - Allows CREATE INDEX CONCURRENTLY
  3. Test on copy of production data - Verify performance impact
  4. Backup before major migrations - Enable rollback capability

PostgreSQL-Specific Migrations

class Migration(migrations.Migration):
    atomic = False  # Required for CONCURRENTLY

    operations = [
        PostgreSQLOnlyRunSQL(
            sql="CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_name ON table(column);",
            reverse_sql="DROP INDEX CONCURRENTLY IF EXISTS idx_name;",
        ),
    ]

Zero-Downtime Migrations

For large tables, use the following pattern:

  1. Add new columns as nullable
  2. Backfill data in batches
  3. Add NOT NULL constraint if needed
  4. Create indexes concurrently

πŸ“ˆ Database Monitoring

Key Metrics

Metric⚠️ WarningπŸ”΄ Critical
Connection count80% of max95% of max
Query duration (p99)500ms2000ms
Table bloat20%40%
Index bloat30%50%
Disk usage70%85%

Useful Queries

-- Active connections
SELECT count(*) FROM pg_stat_activity WHERE state = 'active';

-- Slow queries
SELECT query, calls, mean_time, max_time
FROM pg_stat_statements
ORDER BY mean_time DESC LIMIT 10;

-- Table sizes
SELECT relname, pg_size_pretty(pg_total_relation_size(relid))
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;

-- Index usage
SELECT indexrelname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC;

πŸ’Ύ Backup and Recovery

Backup Strategy

# Full database backup
pg_dump -h localhost -U adsb adsb > backup_$(date +%Y%m%d).sql

# Schema-only backup
pg_dump -h localhost -U adsb --schema-only adsb > schema.sql

# Data-only backup
pg_dump -h localhost -U adsb --data-only adsb > data.sql

Point-in-Time Recovery

Configure WAL archiving in PostgreSQL:

archive_mode = on
archive_command = 'cp %p /backup/wal/%f'

Restore Procedure

# Restore from backup
psql -h localhost -U adsb adsb < backup.sql

# Restore to specific point in time
pg_restore --target-time="2024-01-15 10:00:00" -d adsb backup.dump

πŸ“œ Version History

VersionDateChanges
0.1.02024-01Initial schema with aircraft tracking
0.2.02024-06Added auth, alerts, notifications
0.3.02024-09Added gamification, cannonball mode
0.4.02024-12Performance indexes, archive support