← all methods · TT-009 instrument page · raw markdown: ?raw=1
Grade: OBSERVED. Position, speed over ground, and our own receive clock, from our
own receivers. Nothing modelled, nothing crew-entered.
Status: NOT PUBLISHABLE. Two independent defects push the number toward zero
exactly when congestion is worst. Both are documented below. This file describes a
working instrument that is deliberately not yet reporting.
Average Waiting Rate, the UNCTAD/World Bank congestion indicator:
epsilon = SUM(hours waiting for berth) / SUM(hours alongside berth)
Kek Choo Chung, Port Performance Indicators, World Bank, Transport No. PS-6,
December 1993, indicator 6 (5a/3), codifying UNCTAD's *Manual on a Uniform
System of Port Statistics and Performance Indicators* (1983). In queueing papers the
same quantity is ε = Tw/Ts.
Two things about the definition that are easy to get wrong, and we got both wrong first:
first computed a median of per-call ratios. It read 0.00 at every gateway and
discriminated nothing, and short berth stops made individual denominators tiny so
ratios exploded — STAR SIRIUS led the table at 32.97 on 1.9 hours of "work". A
3-hour service floor appeared necessary to suppress that. **Under the aggregate
the floor is unnecessary**: a short berth simply contributes little to the
denominator. The floor was a symptom of the wrong estimator, and removing it
recovered 35 calls (124 → 159).
| accepted design range | 0.05 – 0.20 |
| PIANC guidance | ~0.165 |
| UNCTAD overutilisation flag | berth occupancy > 70% |
**A bare ε has no fixed meaning without berth count and occupancy, and we can observe
neither.** So ε is published as a comparison across gateways and against the design
range — never as an absolute verdict on a port.
AIS has a field that says "at anchor" (NavigationalStatus = 1). **We do not use
it.** It is crew-set, and the archive shows why: 3,273 BERTH_START events against
153 ANCHOR_START, because crews set moored far more reliably than anchored.
Instead: a ship at anchor swings around its anchor as wind and tide turn it,
tracing an arc a few hundred metres across. **A ship at a berth is held against a
quay by mooring lines and cannot move.** So the spread of positions while stationary
separates the two — and position is GPS off the transponder, which no human types.
Verified 2026-07-30 on 212 stationary runs. The two mechanisms agree independently,
which is this observatory's whole method:
tight (spread <60 m, arc <25 deg) 123 stops median 25 m, 2 deg
-> 85% had the crew declaring MOORED, 0% at anchor
swing (spread >=60 m, arc >=25 deg) 31 stops median 290 m, 168 deg
-> 74% had the crew declaring AT ANCHOR
crew said MOORED n=173 p10 5 m p50 24 m p90 68 m crew said AT ANCHOR n= 29 p10 39 m p50 243 m p90 376 m
spread < 40 m → berth (below the anchored p10)spread >= 120 m → anchor (well above the moored p90)The distributions overlap between 39 and 68 m. A single cut would force a false
binary, so ambiguous stops are labelled and excluded, and the count is published
so a reader can see how much is being set aside.
fix shredded calls: a moored ship's speed reads 0.1, then 1.2, then 0.0 from noise,
and ZIM MOUNT BLANC's single Savannah call came out as six fragments of 0.6–1.5h.
The tell was that berth duration did not scale with ship size — 320–400 m hulls
showed a median 5.0h against 7.7h for 150–250 m hulls, which is backwards.
Fragmentation also converted anchor time into berth time, because a short
fragment of a swinging ship measures tight. Anchor stops rose 41 → 59 once fixed.
closes the run because we cannot claim the vessel stayed put — it does not assert
that it left.
Ships also anchor for bunkers, stores, crew changes, repairs, weather and awaiting
orders, and none of that is queueing. Measured 2026-07-30: of 1,241 observed anchor
hours, only 92 h (7%) are verified as queueing — the other 1,149 h had no
subsequent berth at that gateway. Both figures are reported; only the verified hours
enter the rate.
stop, so an anchor from one visit could be counted as queueing for a berth taken days
later on another. Stops are split into visits, and the boundary is not elapsed
time — observed anchor-to-berth transitions ran from 1.2 h to 37.8 h, so any time
threshold would discard real waiting. The physical test is whether the ship left:
seen beyond 40 nm from the berth centre between two stops, those stops belong to
different visits.
ship_type 70–79 AND LOA >= 150 m. Unfiltered,tugs made "berthings per day" read 745 against an honest 35.
Our bounding boxes reach 5 to 17 nautical miles from centre — Oakland 5 nm,
LA/Long Beach 8 nm, Houston 17 nm.
**In November 2021 LA/Long Beach required waiting ships to hold 150 nautical miles
offshore.** UMAS notes that a 25 nm AIS radius would have reported approximately zero
congestion at the peak of the worst US port crisis on record. For scale: LA's average
wait reached 8.7 days in September 2021, with 86 ships anchored or loitering on
16 November 2021.
So if that event recurred, this metric would not merely miss it — it would fall,
because ships pushed offshore leave the box entirely and never register as anchored.
Of 195 reconstructed calls, **35 anchored but had not berthed when the window closed,
holding 800 of 1,202 observed anchor hours — two thirds of all waiting.** Requiring a
completed call preferentially discards the most congested ships.
**The bias grows exactly when congestion is worst. In a crisis this metric sags
rather than spikes.** That is the worst possible property for a congestion index, and
on its own is sufficient reason for suspension.
Fixes, in order of preference: enough calendar time that the archive is long relative
to typical waits; or an estimator built for censoring (Kaplan–Meier) rather than
dropping incomplete cases.
Where arrival protocols are modern, a ship slow-steams and berths on arrival — **real
delay, zero anchor time.** ε then partly measures how modern a port's arrival protocol
is rather than how congested it is. Not fixable by widening boxes; only by measuring
speed reduction on the final approach leg.
Found 2026-07-30 by building the live board. CAPE DUCATO, CAPE ARUNDEL, `CAPE
SABLE, CAPE STARR` and USNS hulls are US Maritime Administration Ready Reserve
Force vessels. They are AIS type 70–79 and over 150 m, so they pass the merchant
filter, and they sit alongside for months without working cargo.
They hold 345 of 3,515 berth hours — 9.8% of the denominator. Since ε is
wait ÷ berth, padding the denominator deflates ε by roughly a tenth, and more at
Norfolk where three of seventeen berthed hulls are Cape-class. Same class of defect as
the tugboats: a filter that admits the wrong fleet.
Fix: exclude by hull identity, not by name pattern alone — CAPE would also match
legitimate commercial vessels. The vessel registry's operator field already names
the US Navy and MARAD on some of these.
Every long stop reads 63–66 hours, which is the archive length, not a call length. A
genuine container call runs 12–48 hours. So these are floors, not measurements —
"at berth for at least 66 hours" — and they inflate S, which again deflates ε.
Three independent mechanisms now push ε toward zero: right-censoring deletes the
longest waits, window-clipping inflates berth time, and laid-up reserve hulls pad the
denominator. All three flatter the ports. That consistency is the strongest argument
for keeping the series suspended until the archive is long enough for the first two to
become second-order.
Waiting inside the buffer costs almost nothing; only waiting that breaks the schedule
costs money. AIS cannot distinguish them. Stated as a permanent limit.
Report the triplet, because no single figure is sufficient:
| incidence | share of calls that waited at all — a long-standing port KPI ("berth-on-arrival %"), and directly testable against Erlang C |
| epsilon | the aggregate waiting rate — the UNCTAD/World Bank indicator |
| p90 | the tail, in hours not ratio — the bad experience |
The median is deliberately absent and the page must say so: it is 0 by
construction in a low-congestion regime and carries no information.
Print the call count beside every figure. About 15 calls per gateway is too thin
for a stable p90; pool to port-quarter or report incidence and ε only.
Never publish a composite rank. The World Bank's own rank aggregation placed
Beirut 11th on one method and 63rd on the other — same port, same data.
Never publish ε as a bare league table. LA/Long Beach moved record volumes in
2021; the queue was demand exceeding capacity, not port failure, and attributing loss
to the port is a category error. Publish volume beside ε so slow-because-busy is
visibly distinguishable from slow-because-inefficient.
This measures waterside berth queueing only. We cannot see crane moves, gate
transactions, yard density or labour. Bichou's standing critique of the World Bank
CPPI — that examining berth performance alone biases toward shipping-line interests
and ignores landside congestion — applies to this instrument too. Say it in the
method rather than waiting to be told.
UMAS/UCL (December 2024, AIS-derived) find ships spend **4–6% of operational time —
15–22 days a year — waiting at anchor before berthing, as the 2018–2022 norm.**
Container ships sit below that average, and waiting falls with ship size.
So the honest framing is excess above a published baseline, not gross waiting.
Consequence that needs testing: if waiting falls with ship size while service time
rises with it, ε falls doubly with size — so ε could differ between gateways because
of fleet mix rather than performance. calls.gross_tonnage is stored for exactly
this test. It is not yet runnable: only 3 gateways show any waiting at all.
stops one stationary period: kind, minutes, spread_m, heading_arc_deg, fixes calls one port call: wait_minutes, service_minutes, ws_ratio, excluded_because build_runs every rebuild, with the thresholds in force
Derived from the raw archive (ais_position), not by hooking the live detector.
The recorder archives; the analyser derives. A threshold change is therefore a re-run,
not a migration, and nothing is lost to a bug in a state machine. Idempotent: the same
archive produces the same rows.
node calls.js build rebuild stops and calls from the archive, then report node calls.js report report without rebuilding
| check | question |
| coverage | our monthly call count at LA against POLA's published vessel calls — the one gateway with a public denominator |
| fleet mix | does ε correlate with mean vessel size across gateways? If so it is measuring fleet composition |
| incidence vs theory | measured incidence against Erlang C at plausible occupancy. Ours implies 23–44% occupancy; US gateways run 50–70%. Part is genuine (berth windows make arrivals scheduled, not Poisson), part is the geofence gap |
| censoring | median wait of gap-closed against movement-closed calls |
The 40 m / 120 m spread cut is our judgment, so it was tested across seven plausible
alternatives (berth-max 30–68 m against anchor-min 80–150 m) by reclassifying from the
persisted spread_m and recomputing ε:
| gateway | ε across all seven settings |
| savannah | 0.059 – 0.062 |
| la_longbeach | 0.028 – 0.034 |
| oakland | 0.000 – 0.038 — unstable |
| all others | 0.000 throughout |
The threshold choice is not load-bearing where the sample is adequate. Oakland
flips only because its whole figure rests on a single call whose swing fell between
120 and 150 m — a sample-size problem, not a threshold one. **Oakland's ε must not be
quoted.** Incidence is more sensitive (1.3%–3.9%) but stays in the same very-low
regime throughout.
The service-floor sensitivity check (1h/3h/6h) became unnecessary when ε moved to the
aggregate: the floor was removed entirely, so there is no longer a floor to vary.