> ## Documentation Index
> Fetch the complete documentation index at: https://docs.axiomancer.io/llms.txt
> Use this file to discover all available pages before exploring further.

# AIS coverage

> How Overwatch collects AIS vessel positions across the global fleet, configures coverage area and density, and tunes ingestion rates by region and vessel type.

Overwatch receives live AIS position reports through [AISStream](https://aisstream.io) and stores them so that maps, investigations, and cargo estimates always reflect current vessel activity.

By default, Overwatch subscribes to AIS data around each monitored port. Two environment variables let you control how much ocean area is covered.

## Coverage modes

### Port-based coverage (default)

Overwatch computes a bounding box around each port zone polygon and subscribes to AIS messages within that area. The `AISSTREAM_BBOX_BUFFER_DEG` variable controls how far the bounding box extends beyond the port boundary.

| Value           | Approximate radius | Typical vessel count |
| --------------- | ------------------ | -------------------- |
| `0.5`           | \~55 km            | \~1–2 K              |
| `2.0` (default) | \~220 km           | \~3–5 K              |
| `5.0`           | \~550 km           | \~10–20 K            |

A larger buffer catches vessels that are in transit approaching or departing a port, so map views populate before a vessel reaches anchorage.

```bash theme={null}
# Increase the buffer to ~550 km around each port
AISSTREAM_BBOX_BUFFER_DEG=5.0
```

### Global coverage

Set `AISSTREAM_GLOBAL=1` to subscribe to a single planet-wide bounding box (`-90/-180` to `90/180`). This replaces all port-derived bounding boxes and delivers positions for every vessel broadcasting AIS worldwide (\~175,000 distinct vessels).

```bash theme={null}
# Enable global AIS coverage
AISSTREAM_GLOBAL=1
```

<Warning>
  Global coverage delivers **100,000–300,000 vessel positions** at any given time compared to approximately 3,000–5,000 with port-based coverage. Make sure your database and infrastructure can handle the increased write volume before enabling this option.
</Warning>

## In-zone vs. background positions

When `AISSTREAM_GLOBAL=1` is on, Overwatch splits each incoming position by whether the vessel is inside a monitored port or chokepoint bounding box:

* **In-zone positions** (inside any monitored box) behave exactly like port-based coverage. They are written to `ais_positions` history, feed the intelligence pipeline (port events, dark-event detection, course-anomaly scoring, cargo estimation, EWMAs), and update `vessel_states`.
* **Background positions** (outside every monitored box) are map-only. They flow through a latest-wins, per-vessel-throttled buffer directly into `vessel_states` — no `ais_positions` history row, no analytics side effects. The live map's worldwide layer reads from `vessel_states` and `vessels_live_tiles`, so background vessels still appear on the map with a fresh last-known position.

`lastSeen` is still updated on every background frame so that when a vessel later enters a monitored zone after a long ocean transit, the entry is not misread as a dark-event gap.

<Note>
  In-zone behavior is byte-for-byte identical to port-based coverage. The changes below only affect vessels outside the monitored boxes.
</Note>

## Environment variables

### Coverage

| Variable                    | Default | Description                                                                                                             |
| --------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------- |
| `AISSTREAM_BBOX_BUFFER_DEG` | `2.0`   | Buffer in degrees added around each port zone polygon when computing bounding boxes. Ignored when `AISSTREAM_GLOBAL=1`. |
| `AISSTREAM_GLOBAL`          | `0`     | Set to `1` to subscribe to a single worldwide bounding box, bypassing port-derived boxes entirely.                      |

### Background ingestion (`AISSTREAM_GLOBAL=1` only)

These knobs tune how out-of-zone positions are coalesced and written. Defaults are chosen for a \~175 K-vessel global feed; leave them alone unless you are seeing DB pressure or map-freshness issues.

| Variable                           | Default  | Description                                                                                                                                                              |
| ---------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `GLOBAL_BACKGROUND_MIN_INTERVAL_S` | `600`    | Minimum seconds between accepted background writes for the same vessel. Lower values freshen the map faster at the cost of more `vessel_states` upserts.                 |
| `GLOBAL_BACKGROUND_FLUSH_MS`       | `30000`  | How often (ms) the background buffer drains its pending rows to the database.                                                                                            |
| `GLOBAL_BACKGROUND_UPSERT_CHUNK`   | `500`    | Maximum rows per background upsert batch. Lower this if you hit statement-size limits.                                                                                   |
| `STATIC_DATA_DB_MIN_INTERVAL_S`    | `21600`  | Minimum seconds between database writes of Type 5 static data (name, IMO, dimensions) for the same vessel. The in-memory MMSI→IMO cache is still updated on every frame. |
| `MMSI_RECOVERY_RETRY_S`            | `1800`   | Minimum seconds between database lookups when trying to recover an IMO for an unknown MMSI. Prevents one query per position for vessels that will never be resolved.     |
| `AIS_MAX_STUBBED_IMOS`             | `300000` | Maximum entries in the in-memory stub-vessel cache. Sized above the global fleet (\~175 K) so the cache is not repeatedly cleared under global-mode load.                |

Example: freshen the worldwide map every 5 minutes and drain every 15 seconds.

```bash theme={null}
AISSTREAM_GLOBAL=1
GLOBAL_BACKGROUND_MIN_INTERVAL_S=300
GLOBAL_BACKGROUND_FLUSH_MS=15000
```

## When to adjust coverage

* **Maps look empty far from port** — increase `AISSTREAM_BBOX_BUFFER_DEG` to catch in-transit vessels earlier.
* **You want worldwide last-known coverage on the live map** — enable `AISSTREAM_GLOBAL=1`. Background positions keep the map fresh without writing full position history for the whole planet.
* **Background writes are still too heavy** — raise `GLOBAL_BACKGROUND_MIN_INTERVAL_S` (fewer accepted samples per vessel) or `STATIC_DATA_DB_MIN_INTERVAL_S` (fewer static-data upserts).
* **Storage or compute costs are too high** — reduce `AISSTREAM_BBOX_BUFFER_DEG` to limit data volume, or leave global mode off.

<Note>
  Position data is automatically downsampled and archived over time to manage storage. See [data retention and downsampling](/overwatch/data-retention) for details on retention windows and resolution tiers.
</Note>
