At a glance
- Level
- Intermediate
- Time
- 11 min
Prerequisites
- state_vectors, flights and coverage_cells models (see the ADS-B ingestion guide)
- Optional: nav_quality_cells for interference alerts (see the GNSS interference guide)
- Reference geometry: aerodromes, published holding areas, and restriction polygons from official notices
- A destination for alerts (Kimo inbox, email, Slack or webhook) and a named owner per rule
You will end up with
Five production-ready rule patterns in Kimo YAML, with persistence, coverage gating, grouping and suppression, plus a precision dashboard and review routine.
Connectors used
Air traffic data generates an inexhaustible supply of things that look odd: go-arounds, holds, reception glitches, training flights. An alerting layer that reports all of them gets muted, and then the one alert that mattered is missed. Google's SRE guidance puts the principle plainly: "Every page should be actionable," and when pages occur too frequently, people "second-guess, skim, or even ignore incoming alerts"3Source 3 · Google (sre.google), 2016Site Reliability Engineering, Chapter 6: Monitoring Distributed Systemssre.google. This guide applies that discipline to open airspace data. All examples use civil, cooperative surveillance data and simulated aircraft.
§01What makes an airspace alert trustworthy?
Trust comes from predictability. The SRE book also advises that the rules catching real incidents most often "should be as simple, predictable, and reliable as possible", and that it is better to alert on symptoms than causes3Source 3 · Google (sre.google), 2016Site Reliability Engineering, Chapter 6: Monitoring Distributed Systemssre.google. For airspace work we turn that into six properties every rule must have before it is enabled.
| Property | Question it answers | Example |
|---|---|---|
| Actionable | What should the analyst do when it fires? | "Check ATC/authority channels and brief the duty officer" |
| Persistent | How long must the condition hold? | Squawk 7700 seen in ≥ 3 messages over ≥ 10 s |
| Coverage-gated | Could this be a reception artifact? | Only evaluate cells with adequate coverage this hour |
| Baselined | Is this unusual here, now? | Compare with the same cell, hour and weekday over 28 days |
| Grouped | Is this a new incident or the same one? | One alert per aircraft per 30 minutes, updated in place |
| Owned | Who reviews and tunes it? | Named owner, purpose, review date |
§02Anatomy of a Kimo alert rule
Kimo alert rules are YAML files next to your models, versioned and reviewed like code. Every change appears in the activity log with a diff. A rule has a model to watch, a condition, persistence, gates, grouping, enrichment and routing. See the alerts documentation for the full schema; the excerpts below use the fields that matter for airspace.
rule: <id>
owner: <person or team>
purpose: <one sentence: what action this alert should trigger>
model: state_vectors | flights | nav_quality_cells
condition: <SQL boolean over the model>
persist: { min_messages: 3, min_duration: 10s, min_receivers: 1 }
gates:
coverage: required
baseline: { window: 28d, compare: same_hour_weekday }
group_by: [icao24] # or [h3_cell], [restriction_id]
suppress_for: 30m
enrich: [track_15m, nearest_aerodromes, weather, notices]
severity: low | medium | high
route: [inbox, slack:#airspace-duty]
review: monthly§03Rule 1: emergency squawks without false alarms
Three Mode A codes have special meaning. The FAA AIM tells pilots to select 7700 in an emergency ("SQUAWK MAYDAY")1Source 1 · Federal Aviation AdministrationAeronautical Information Manual, Chapter 4 Section 1 (4-1-20 and 4-1-21)faa.gov, 7600 after losing two-way radio2Source 2 · Federal Aviation AdministrationAeronautical Information Manual, Chapter 6 Section 4 (6-4-2)faa.gov, and describes 7500 as the hijack code1Source 1 · Federal Aviation AdministrationAeronautical Information Manual, Chapter 4 Section 1 (4-1-20 and 4-1-21)faa.gov. The same section warns that pilots should avoid inadvertently selecting 7500, 7600 or 7700 during routine code changes, because it causes "momentary false alarms at automated ground facilities"1Source 1 · Federal Aviation AdministrationAeronautical Information Manual, Chapter 4 Section 1 (4-1-20 and 4-1-21)faa.gov. That is the single most important input to this rule: an emergency code seen once is not an emergency.
The good news is that persistence costs little latency. Under ADS-B version 2 the aircraft-status message, which carries the squawk, is broadcast at 0.2 Hz normally but at 1.25 Hz when the code changes7Source 7 · Junzi Sun, TU Delft (mode-s.org)The 1090 Megahertz Riddle (2nd ed.) — ADS-B basicsmode-s.org, and position messages arrive at about 2 Hz. A genuine emergency code produces several messages within seconds. That holds for your own receivers; if you poll a state-vector API every 30–60 seconds instead, each row is already a snapshot, so express persistence as min_duration across two or more consecutive polls rather than as a message count.
rule: emergency_squawk
owner: airspace-duty
purpose: Bring context together fast when an aircraft persistently squawks an emergency code.
model: state_vectors
condition: squawk in ('7700', '7600', '7500')
persist:
min_messages: 3
min_duration: 10s
same_code: true # code must not flicker between values
gates:
coverage: not_required # emergencies matter even at the edge of coverage
exclude:
- on_ground = true and gs_ms < 5 # parked aircraft testing transponders
group_by: [icao24, squawk]
suppress_for: 60m
enrich: [track_15m, altitude_profile_15m, nearest_aerodromes, weather, notices]
severity:
'7700': high
'7600': medium
'7500': high
route:
'7500': [inbox:restricted] # never broadcast; restricted audience only
default: [inbox, slack:#airspace-duty]
review: monthlyEnrichment is what makes the alert useful. The analyst should see the last 15 minutes of track and altitude, the nearest aerodromes, and current weather there. Weather comes from an official source; for example, the US Aviation Weather Center's Data API serves METARs, TAFs and SIGMETs, limits clients to 100 requests per minute and asks for a custom user agent4Source 4 · NOAA / National Weather Service Aviation Weather CenterAviation Weather Center Data APIaviationweather.gov. Cache observations per aerodrome rather than calling the API per alert.
§04Rule 2: loitering away from expected holds
Circling is normal near busy aerodromes and published holding areas, and for survey, medical or police aircraft. It is noteworthy near a declared incident site or in an area where no such activity is expected. The rule measures accumulated turning inside a small radius, excludes published holds and aerodrome vicinities, and requires coverage so a track that merely drifts in and out of reception is not mistaken for a loop.
rule: loitering_unexpected
owner: airspace-analysis
purpose: Flag sustained circling outside holds and aerodrome areas for analyst review.
model: flights
window: 20m
condition: >
cumulative_heading_change_deg >= 720
and max_distance_from_centroid_m <= 5000
and not within(centroid, published_holds)
and distance_to_nearest_aerodrome_nm(centroid) > 10
persist: { min_duration: 10m }
gates:
coverage: required
baseline: { window: 28d, compare: same_cell, max_rate_per_day: 0.5 }
group_by: [icao24]
suppress_for: 60m
enrich: [track_30m, notices, nearest_aerodromes]
severity: low
route: [inbox]
review: monthlyThe baseline gate is what prevents fatigue here: if a cell routinely sees circling (a flight school area, an aerial survey corridor), it will exceed max_rate_per_day in the baseline and the rule stays quiet there. Severity is low on purpose. Loitering is a prompt to look, rarely more.
§05Rule 3: unusual altitude profiles
Rapid descents outside approach phases, prolonged level-offs at unusual levels, or repeated climb-descend cycles can indicate an aircraft in difficulty. They can also indicate a data problem, so this rule depends on good altitude data: barometric altitude only (never mixed with geometric altitude), from aircraft heard by enough receivers, and with the ingestion model's implausible_jump flag false.
rule: rapid_descent_enroute
owner: airspace-duty
purpose: Surface sustained rapid descents away from aerodromes for immediate review.
model: state_vectors
condition: >
vrate_ms <= -25
and baro_alt_m > 3000
and distance_to_nearest_aerodrome_nm(lat, lon) > 25
and not implausible_jump
persist: { min_messages: 20, min_duration: 45s }
gates:
coverage: required
min_receivers: 2
group_by: [icao24]
suppress_for: 30m
enrich: [altitude_profile_15m, track_15m, squawk_history, weather, nearest_aerodromes]
severity: medium
escalate:
when: squawk in ('7700')
to: high
route: [inbox, slack:#airspace-duty]
review: monthlyA vertical rate of −25 m/s is about 4,900 ft/min. The thresholds above are starting points chosen by our team for civil traffic, not regulatory values. Tune them on your own history: replay a month of data, count how often the rule would have fired, and read every hit. If more than a handful per week are explained by routine operations, tighten the distance or persistence before enabling it.
§06Rule 4: geofences from official notices
Geofence rules are only as good as their polygons. Build them from official sources (temporary restrictions around disasters, major events or wildfire operations published as NOTAMs or national equivalents), with altitude bands and validity windows, and never from hand-drawn shapes that outlive their purpose. Kimo stores each restriction with its source reference and expiry, and the rule only evaluates active restrictions.
rule: active_restriction_entry
owner: airspace-duty
purpose: Notify when a track enters an active, officially published temporary restriction.
model: state_vectors
join: restrictions # polygons with alt_min_m, alt_max_m, valid_from, valid_to, source_ref
condition: >
within(point(lon, lat), restrictions.geom)
and baro_alt_m between restrictions.alt_min_m and restrictions.alt_max_m
and obs_time between restrictions.valid_from and restrictions.valid_to
persist: { min_messages: 4, min_duration: 15s }
gates:
coverage: required
exclude_categories: [] # do not assume exemptions; let analysts decide
group_by: [icao24, restrictions.id]
suppress_for: 45m
enrich: [track_15m, restrictions.source_ref, notices]
severity: medium
route: [inbox]
review: per_restrictionExpect legitimate entries: emergency services, authorized media, and aircraft operating under the restriction's own exemptions. The alert asks a question; it does not assert a violation. Note also that US rules allow authorized aircraft on sensitive government missions not to transmit ADS-B6Source 6 · Cornell Law School Legal Information Institute14 CFR § 91.225 — ADS-B Out equipment and uselaw.cornell.edu, so the absence of alerts is not evidence that a restriction is clear.
§07Rule 5: GNSS interference cells
The interference layer from the GNSS interference guide produces an indicator band per cell and window. Alerting on every high cell would page all day in affected regions. Instead, alert on a cluster of adjacent high cells that persists for two consecutive hours and is not already covered by an active notice. The EASA–IATA mitigation plan calls for standardized NOTAM Q-codes for GNSS interference5Source 5 · EASA press release, 2025EASA and IATA publish comprehensive plan to mitigate GNSS interferenceeasa.europa.eu, which makes that last check increasingly automatable.
rule: interference_cluster_new
owner: nav-quality
purpose: Flag new, persistent clusters of degraded GNSS indications not covered by active notices.
model: nav_quality_cells
condition: >
indicator_band = 'high'
and sample_ok and coverage_ok
cluster:
method: h3_neighbors
min_cells: 3
persist: { consecutive_windows: 2 }
gates:
exclude: covered_by_active_notice(cluster_geom, q_codes: [gnss])
baseline: { window: 28d, compare: same_cluster, novelty: true }
group_by: [cluster_id]
suppress_for: 12h
enrich: [band_by_altitude, eligible_aircraft, notices, authority_regions]
severity: low
route: [inbox, email:nav-quality-team]
review: monthly§08Which rules should you build first?
Not all five rules deserve to go live on day one. Order them by how clearly the event maps to an action and by how much tuning the rule needs before it is quiet enough to trust. Emergency squawks come first: the meaning is defined by published procedure, the false-alarm mechanism is documented, and persistence handles it. Restriction entries come next, because the polygon and validity window come from an official notice. Interference clusters follow once you have a month of baseline. Rapid descents and loitering come last, because they need the most local tuning.
| Order | Rule | Why this position | Typical tuning effort |
|---|---|---|---|
| 1 | Emergency squawk | Meaning set by procedure; clear action | Low: persistence only |
| 2 | Active restriction entry | Geometry and validity from official notices | Low to medium: polygon hygiene |
| 3 | Interference cluster | Needs baseline and coverage model | Medium: one baseline month |
| 4 | Rapid descent en route | Sensitive to altitude data quality | Medium: replay and read hits |
| 5 | Loitering | Many routine explanations | High: per-area exclusions |
What should the alert itself say?
A trusted alert explains itself in one screen. Kimo renders every airspace alert with the same four parts: what fired (rule name and the exact condition, with values), why it is believed (message count, duration, receivers, coverage status), context (track, altitude profile, weather, active notices), and what to do (the purpose sentence from the rule, plus the owner). Analysts should never have to reverse-engineer a rule to decide whether an alert is real, and when they label it, that label should be one click away from the evidence.
§09How do you keep alert fatigue under control?
Fatigue is a measurable quantity. Track three numbers per rule and review them monthly with the rule owner: precision (alerts an analyst marked useful divided by alerts delivered), volume per shift, and time to acknowledge. A rising acknowledge time with flat volume is the earliest sign that people have started to skim.
- Emergency squawk rule
- Loitering rule
- Step 1:
Replay before enabling
Run each new rule against 30 days of history in shadow mode and read every hit. Enable only if you would have wanted most of them.
- Step 2:
Label every alert
One click: useful, expected, artifact. Labels feed the precision metric and the next tuning round.
- Step 3:
Tune the gate, not the threshold first
Most noise comes from coverage edges and routine locations. Fix gates and baselines before loosening or tightening the core condition.
- Step 4:
Cap volume per rule
If a rule exceeds its weekly budget, it degrades to a digest automatically and notifies its owner.
- Step 5:
Retire honestly
A rule below 30% precision for two consecutive reviews is rewritten or removed. Interesting is not the same as actionable.
Pre-launch checklist for any airspace rule
- Purpose sentence written in terms of an action.
- Persistence defined (messages, duration, receivers).
- Coverage gate set, or explicitly waived with a reason.
- Baseline comparison defined for spatial rules.
- Grouping and suppression window set.
- Enrichment attached so the analyst does not open five tabs.
- Routing respects sensitivity (restricted audience where needed).
- Owner and review cadence recorded.
- Shadow-mode replay completed and read.
§10Troubleshooting noisy or silent rules
| Symptom | Likely cause | Fix |
|---|---|---|
| Squawk alerts that clear in seconds | Momentary code selection during routine changes | Increase min_messages and require same_code |
| Loitering alerts near one field every weekend | Flight school or glider activity | Add the area to the baseline or a named exclusion |
| Rapid-descent alerts with odd altitudes | Mixed barometric and geometric altitude, or decoding errors | Use barometric only; require min_receivers: 2 |
| Bursts of alerts at the edge of the map | Coverage boundary artifacts | Enable the coverage gate |
| Interference rule silent during a known event | Cells below minimum sample or already covered by a notice | Check sample_ok; the notice exclusion is working as intended |
| Analysts stopped acknowledging | Volume above budget for weeks | Cap, digest, and review precision with owners |
All five rules ship, disabled and pre-tuned for simulated data, in the Airspace watch template. Open the Airspace view to see them firing on the demo dataset, read the blog post on emergency squawks and anomaly alerting, or step back to the strategy in the whitepaper Airspace Awareness from Open Data. If your rules must run where the data lives, Kimo Bridge and the on-premise deployment keep evaluation inside your network.
Sources
7 references- Aeronautical Information Manual, Chapter 4 Section 1 (4-1-20 and 4-1-21) (opens in a new tab)Federal Aviation Administrationfaa.gov
Inadvertent selection of 7500/7600/7700 causes momentary false alarms; 7500 hijack code; SQUAWK MAYDAY = 7700.
- Aeronautical Information Manual, Chapter 6 Section 4 (6-4-2) (opens in a new tab)Federal Aviation Administrationfaa.gov
Code 7600 on loss of two-way radio capability.
- Site Reliability Engineering, Chapter 6: Monitoring Distributed Systems (opens in a new tab)Google (sre.google)2016sre.google
Every page should be actionable; frequent pages get ignored; simple, predictable rules; symptoms over causes.
- Aviation Weather Center Data API (opens in a new tab)NOAA / National Weather Service Aviation Weather Centeraviationweather.gov
METAR, TAF, SIGMET endpoints; 100 requests per minute; custom user agent.
- EASA and IATA publish comprehensive plan to mitigate GNSS interference (opens in a new tab)EASA press release2025easa.europa.eu
Standardized NOTAM Q-codes for GNSS interference.
- 14 CFR § 91.225 — ADS-B Out equipment and use (opens in a new tab)Cornell Law School Legal Information Institutelaw.cornell.edu
Transmit-at-all-times rule and authorized exceptions for sensitive government missions.
- The 1090 Megahertz Riddle (2nd ed.) — ADS-B basics (opens in a new tab)Junzi Sun, TU Delft (mode-s.org)mode-s.org
Aircraft status broadcast at 0.2 Hz, 1.25 Hz when the squawk changes; position at 2 Hz.
External sources were accessed at the time of writing. Kimo product details, customers and figures in examples are illustrative unless a source is cited.
Mark as done
0 of 10 sections done
Frequently asked questions
How long should an emergency squawk persist before alerting?
We default to at least three messages over at least ten seconds with the same code. Because the status message rate rises to 1.25 Hz when the code changes, a genuine emergency code meets that bar within seconds while momentary mis-selections do not.
Should loitering alerts be high severity?
Rarely. Circling has many routine explanations, so loitering is a low-severity prompt to look, gated by baseline and exclusions for holds and aerodromes.
Where should geofence polygons come from?
From official notices with altitude bands and validity windows, stored with their source reference and expiry. Hand-drawn polygons tend to outlive their purpose and create noise.
How do I measure alert fatigue?
Track precision (useful alerts divided by delivered alerts), volume per shift and time to acknowledge for each rule, and review them monthly with the rule owner.
Can alerts run without sending data to Kimo’s cloud?
Yes. With Kimo Bridge or an on-premise deployment, rules are evaluated against data that stays in your network.
Skip the setup — start from a working version.
Airspace watch: Live air picture with emergency squawks, loitering and geofence alerts.


