kimo
Engineering

Finding dark vessels: AIS gaps at scale

A ship that switches off its transponder is not automatically suspicious — coverage is patchy, equipment fails, and some vessels are legally exempt. The signal is in the context: where the gap happened, how long it lasted, and what the ship did next.

Jonas Becker
Defense programs12 min read

The Automatic Identification System (AIS) was designed for collision avoidance, not surveillance. Vessels broadcast their identity, position, course and speed every few seconds to a few minutes, depending on speed and class. Terrestrial receivers pick these up within roughly 40 nautical miles of the coast; satellite receivers fill in the open sea, with longer revisit times.

A “dark” period is any interval where we expected to hear from a vessel and did not. The naive approach — flag every gap longer than N hours — drowns analysts in noise. In a simulated North Sea dataset of 11,000 vessels over 30 days, a flat 6-hour threshold produced over 2,300 alerts per day. Almost all were coverage holes.

§01Step 1 — Model when you should have heard from it

The first step is to replace “time since last message” with “messages missed”. For each vessel and each segment of its track we estimate an expected reporting interval from its class, speed, and the receiver coverage of the area it was in. A gap is then scored by how many expected reports were missed, not its raw duration.

gaps.sql — find candidate gaps with window functions
sql
with pings as (
    select
        mmsi,
        ts,
        lat,
        lon,
        sog,
        lag(ts)  over w as prev_ts,
        lag(lat) over w as prev_lat,
        lag(lon) over w as prev_lon
    from ais.positions
    where ts >= now() - interval '30 days'
    window w as (partition by mmsi order by ts)
)
select
    p.mmsi,
    p.prev_ts                                   as gap_start,
    p.ts                                        as gap_end,
    extract(epoch from p.ts - p.prev_ts) / 3600 as gap_hours,
    st_distance(
        st_point(p.prev_lon, p.prev_lat)::geography,
        st_point(p.lon, p.lat)::geography
    ) / 1852                                    as gap_nm,
    c.expected_interval_s
from pings p
join coverage.cells c
  on c.h3 = h3_lat_lng_to_cell(p.prev_lat, p.prev_lon, 5)
where p.ts - p.prev_ts > make_interval(secs => 6 * c.expected_interval_s);

The coverage table is the unsung hero. We aggregate receiver hits into an H3 grid and compute, per cell and per hour of day, the median interval between consecutive messages from all vessels. A gap inside a cell where everyone goes quiet is a coverage problem. A gap where everyone else keeps talking is interesting.

§02Step 2 — Score the gap in context

Candidate gaps then go through a scoring model. We deliberately use an interpretable additive score rather than a black box: analysts need to see why something was flagged, and the score must be defensible in a report.

FeatureWeightRationale
Missed reports vs coverage baseline0.30Separates silence from blind spots
Implied speed across the gap0.20Unrealistic jumps suggest spoofing or loitering
Distance from expected route0.15Deviation from typical lanes for the vessel class
Proximity to other dark vessels0.15Possible ship-to-ship transfer
Port call history0.10Recent calls at ports of interest
Weather severity−0.10Storms explain equipment drop-outs
Illustrative weights from the simulated model. In deployments they are tuned per area of operation.

Weather enters with a negative weight. A gap during force-9 winds is less surprising, and showing that a factor reduced a score is just as useful to an analyst as showing what raised it.

Daily candidate gaps vs flagged events
  • Candidate gaps (÷10)
  • Flagged for analyst
Figure. Simulated 10-day window. The contextual score cuts daily alerts by two orders of magnitude while retaining all 23 injected test events.

§03Step 3 — Fuse with other feeds

AIS positions, map context, open-source reporting and a streaming bus for live tracks.

A flagged gap is a lead, not a conclusion. Kimo Defense Intelligence attaches context automatically: nearby vessels during the gap, the last and next port calls, any open-source reporting that mentions the vessel name or IMO number, and — where available — imagery tasking windows that overlap the gap.

  • Rendezvous candidates — other vessels that were dark in the same H3 cell within ±6 hours.
  • Identity checks — changes of name, flag or MMSI before and after the gap.
  • Pattern of life — whether this vessel has gone dark in the same area before.

§04Step 4 — Close the loop with analysts

Every flagged event lands in a queue where an analyst marks it as explained, of interest or false positive, with a free-text note. Those labels feed back into weight tuning each week. In the simulated deployment, the median time from gap end to analyst triage fell to seven minutes, and the false-positive rate dropped from 61% to 18% over six weeks of feedback.

−99%
alerts vs flat threshold
7 min
median time to triage
18%
false positives after tuning

The full pipeline runs on-premise, including the coverage model and the scoring service. Read how a (fictional) maritime authority deployed it in the anonymized case study, or explore simulated tracks in the map view of the demo.

  • #Maritime
  • #AIS
  • #Anomaly detection
Found this useful? Pass it on.
Written by
Jonas Becker
Defense programs at Kimo · 2 articles

Writes about ADS-B, Alerting, Airspace, Maritime.

People, companies and figures in this article are illustrative; charts use simulated data. All aircraft data shown in Kimo is simulated.

Put it to work

Go deeper

Whitepaper

Airspace Awareness from Open Data

ADS-B, Mode-S and GNSS interference: what open aviation data can reveal, its limits, and how to fuse it responsibly.

32 pages
Template

Airspace watch

Live air picture with emergency squawks, loitering and geofence alerts.

4 min setup
Live demo

Open Airspace

Tracks, emergency squawks and a GNSS-interference map on a simulated feed.

Simulated data · no sign-up

All resources
ArticleEngineering
Defense

Airspace awareness from open ADS-B data

How ADS-B works, what open receiver networks can and cannot tell you, and how to fuse it into one air picture.

Hugo Lefèvre
12 min read
Definition
Defense

AIS (Automatic Identification System)

AIS (Automatic Identification System) is a VHF radio system that ships use to broadcast their identity, position, course, speed and navigational status automatically to other ships, shore stations and aircraft.

Kimo team
3 min read

Airspace awareness from open data.

Fuse ADS-B, AIS and OSINT feeds on your own infrastructure. The demo runs entirely on simulated data.