Ports & Congestion - Complete User Guide
This guide covers the three connected screens that make up the Ports & Congestion area: the searchable Ports directory (/ports), the deep per-port page (/port/<code>) with its four tabs and Port Activity Index, and the live Congestion board (/congestion). Every visible element is documented straight from the templates so you know exactly what each number means and how to act on it as a charterer, broker or owner.
The Ports directory (/ports) - find any active port
The directory is the entry point. It lists only ports with current activity (a port surfaces only if at least one ship is in port, arriving, or recently departed) and is paged 20 at a time.
- Search box (top-left, max ~420px wide): type a port name, LOCODE or country. It debounces ~300ms (
setTimeout(apply,300)) and re-queries the server, so partial matches work as you type. Each keystroke resets you to page 1. The backend match is broad - it tests your text against code, name, country and region. - Count line (top-right, grey muted text): reads e.g. "412 ports with activity · showing 1-20 (page 1/21)". The first number is the total matching ports; the rest tells you which slice you're viewing. When a query returns nothing the slice shows
0. - Table columns: Code (the UN/LOCODE - a blue link,
a.p, straight into the port page), Port, Country, Region, then three live count columns rendered right-aligned (class="n"): In port now = distinct ships with an open Port/Anchorage interval right now; Arriving = ships whose declared AIS destination resolves to this port; Departed = distinct ships that recently had a closed Port/Anchorage interval here. - Row click: the whole row is clickable (
cursor:pointerontbody tr). Clicking anywhere except the code link navigates to/port/<code>; the code itself is a normal link, so middle-click / open-in-new-tab works there. - Pager: ← Prev / Next → buttons (disabled at the ends) plus a "Page X / Y · 20 per page" readout. The page number is written into the URL (
?page=viahistory.replaceState, dropped when on page 1) so you can bookmark or share a deep page.
How to read it: rows arrive ranked by total activity, so the busiest ports float to the top of page 1. Two pseudo-ports - Orders / Unspecified (_ORDERS) and Unresolved (raw destination) (_OTHER) - exist for data-quality review and are admin-only; regular users never see them in the list or open their detail. Why it matters: this is your fastest route to a specific load/discharge port's live picture, and the Arriving column is an early read on inbound competition for berths.
Port page header, filter bar and the four tabs
Each port page opens with a header block and a filter bar, then a four-tab layout. Your last-used tab is remembered in the browser (localStorage 'port_tab'), so a user who lives in "Seasonality" lands there on the next visit.
- Header: a ← Ports back-link, the port name with its LOCODE in parentheses (e.g. Tubarão (BRTUB)), a sub-line showing Country · Region · lat, lon, and an all-time totals line: Moored N ship-days · Anchorage N ship-days · N ships ever. Ship-days are cumulative vessel-time spent moored vs at anchorage across all history - a quick gauge of how heavily used and how congestion-prone the port is.
- Filter bar: From / To date pickers, a Show dropdown (All / In port now / Arriving / Departed) and a State dropdown (Port + Anchorage, Port (moored), or Anchorage). Hit Apply to re-query
/api/portwith those parameters. Use State = Anchorage to isolate the waiting queue, or a date range to study a past period. - Tab bar: Now (carries a pill badge set to the live count = in-port + arriving), Activity, Seasonality, Breakdown. The active tab's badge flips to the accent colour. The Now badge gives you the headline congestion-plus-inbound number without opening anything; the other three tabs are intentionally un-badged because their content depends on the chosen window.
- Sticky behaviour: the tab bar is
position:stickyat the top, so it stays visible as you scroll long tables. Charts are SVG and redraw on tab-show and on window resize (a chart drawn while its tab was hidden would otherwise be 0-wide). - Pseudo-port fallback: for the admin-only
/port/_ORDERSand/port/_OTHER, the filter bar and all four tabs are hidden and a single "By declared text" table appears, grouping raw, un-geocoded destination strings by ship count - useful only for spotting data gaps. - Failure state: if
/api/portreturns a non-OK status or an error, the title flips to "<CODE> - failed to load" with a red message and a hard-refresh hint plus a link back to/ports, and a toast - rather than silently showing empty zeros.
Under the port header you’ll also see “⚓ Deepest-draught arrival on record”: the most heavily-laden vessel observed entering this port, with its arrival draught, DWT and date. It answers a practical question at a glance - what is the deepest-draught ship that can actually get in here? It is computed from real per-leg arrival draughts with physically-impossible readings filtered out (so one bad fix can’t fake the maximum), and it updates automatically: the moment a deeper-draught ship arrives, it takes the record.
Tab 1 - Now: who is at the port today
The Now tab is the operational snapshot - three lists answering "what's happening at this berth right now," each in a scrollable panel and each with a live count in its heading.
- In port now (N): every ship with an open interval here. Columns: Ship (opens the ship page in a new tab), IMO, State (relabelled Moored for Port, Anchorage for anchorage, via the
LBLmap that also handles At sea/Idle), Since (UTC) (when that interval began), Moored here (d) and Anchorage here (d) (this ship's lifetime days in each state at this port), Visits, Type, and Declared dest. A small amber feed pill (bordered, font-size 9.5px) appears on rows whosesourceisfreight- i.e. the in-port status came from the position feed and there is no AIS-derived interval yet, so treat its timing as softer. - Arriving (declared destination, N): ships whose declared destination points here. Columns: Ship, IMO, ETA, Status, Declared dest. An amber ≈ symbol (with tooltip "matched by name + position proximity") flags a fuzzy match rather than an exact LOCODE - verify those before relying on them. Note: on a pseudo-port this heading text changes to "Ships (declared destination, …)".
- Departed (N): recently closed visits. Columns: Ship, IMO, State, Arrived (UTC), Departed (UTC), Moored total (d), Anchorage total (d), Visits.
Why it matters: the In-port + Arriving lists show your real-time competition for tonnage or berths; the per-ship Anchorage here (d) tells you how long a specific vessel has actually been stuck waiting. The Departed list is your tonnage-opening radar - a ship that just left a port is potentially open for the next fixture.
The Port Activity Index (PAI) banner and tiles
On the Now tab, above the lists, sits the Port Activity Index banner. It always renders, but when the port has no qualifying laden departures in the coverage window it shows an explanatory dashed empty-state ("No qualifying laden departures recorded… minimum N laden voyages per band to publish a score…") rather than a broken blank.
- What it measures: LOADING (export) activity only. The blue info box states this plainly - a tile appears for a ship class only if a vessel actually loaded cargo here and sailed out laden. Ships that arrive to discharge (imports), bunker, or for repair/shipyard work leave in ballast and do not count - so a heavy import or shipyard port (the box names Tuzla) can legitimately show few or no PAI tiles. For the full arrival picture, use the Breakdown tab.
- How it is built: PAI combines a volume index - how much this port loads versus a typical world port in its DWT band (the main driver - “how much it loads”) - with a secondary speed index - how fast it turns ships round versus the band norm (an efficiency modifier, extremes capped). 1.00 = global baseline; >1 = busier loading hub, <1 = quieter.
- The tiles / bands: one tile per DWT band on an 11-band axis (
0-5K, 5-10K, 10-17.5K, 17.5-30K, 30-47K, 47-55K, 55-68K, 68-90K, 90-120K, 120-190K, 190-250K), drawn small-to-large. Each active tile shows the band name (uppercase), a status word (top-right), the big PAI × figure (e.g.1.42×), and a detail line:N laden dep · vol N× · spd N× · Nd wait+berth. Bands with no laden departures render as a faded "-" / "no laden dep" tile so the whole spectrum is visible. - Colour / status code: green = "premium hub" (PAI ≥ 1.5), amber = "on par" (0.8-1.5), pink = "quiet" (< 0.8). Each tile's left border carries the same colour.
- The sub-line (next to the heading) states the actual coverage ("last N d") and that the baseline is a robust world benchmark across ports of the same class, built so that thin samples cannot distort it. A single departure simply reads as "quiet."
Why it matters: a green PAI for your vessel's band tells you this is a firm loading hub where rates and charters tend to run premium; a pink tile says the port is quiet for that size - useful when deciding where to position for cargo.
Tab 2 - Activity: density calendar, monthly turnaround, and the 52-week chart
The Activity tab is three time-series blocks (each hidden until it has data) that show how traffic and waiting have evolved.
- Daily ship traffic - density calendar: a GitHub-style heatmap where each small square is one day. The legend runs Less → More across five shades (
#13263fempty, then#1f4e7a / #2f74b5 / #4a9fe0 / #7ec8ff); darker = fewer ships that day, lighter = more. Three radio toggles pick the metric: Total (unique ships), Moored (ships at berth), Anchorage (ships waiting offshore). Hover any square for the exact date and counts ("N ships (M moored, K anchorage)"). The summary appends "· peak N ships on DATE · N active day(s)" - "active days" is how many days in the window had any traffic, and it grows as the port collects more data. - Monthly traffic & turnaround: a horizontal bar chart (bar length = arrivals, label "N arr · M dep") plus a table: Month, Arrivals, Departures, Avg wait (d), Avg berth (d). Empty cells show "-". This is your turnaround trend - rising Avg wait with flat berth time signals queue build-up, not slower handling.
- Weekly arrivals (rolling window): a stacked SVG bar chart, one bar per ISO week. Legend: green = arriving in ballast (empty), blue = arriving laden (cargo on board), grey = load not declared. An orange line with dots overlays the average anchorage wait that week (right axis, in days; left axis = arrival count). Hover any bar segment or dot for exact figures. The heading honestly labels the real depth (" - last N weeks" with a coverage note when under a year), and a summary reads "· N arrivals (B ballast · L laden · U unknown)." Why it matters: a rising blue share means more loaded inbound cargo (a discharge port firming); a climbing orange line marks the bottleneck weeks.
Tab 3 - Seasonality: month-of-year pooling and anchorage-vs-berth
The Seasonality tab rolls the same underlying data into recurring-pattern views - useful for anticipating harvest, grain or monsoon cycles before they hit rates.
- PAI seasonal factor: a 12-month strip showing each calendar month’s berth-call activity as a multiple of this port’s own average month (1.00× = a typical month, >1 busier, <1 quieter), built from the deep call record rather than the thinner 12-month voyage table. A full year of accrued history is needed before the pattern is reliable, so until then it reads building N/12 and is kept out of the live PAI number - it fills in and flips to Active automatically as history deepens.
- Seasonality - Jan to Dec, pooled across all years: a 12-bar SVG chart, one bar per calendar month with all years combined. Bars are stacked by load the same way as the weekly chart - laden (blue), ballast (green), unknown (grey) - with the total count printed above each bar and the month label below. Hover for exact counts. Read it to spot which months this port consistently runs hottest (e.g. a Q3 harvest peak or Q4 grain surge).
- Anchorage queue vs. berth utilisation (weekly): a dual-line SVG, one point per ISO week, plotting the average number of ships per day at anchorage (orange) and moored at berth (blue). A top-left caption shows the peak ships/day. The guidance is explicit: anchorage rising faster than berth = congestion building. When the orange line pulls away from the blue, the port is taking ships faster than it can berth them - the leading indicator of demurrage exposure and firming load-port rates.
Tab 4 - Breakdown: vessel mix, trade origins/destinations, tonnage and segments
The Breakdown tab answers "what kind of ships call here, and where does this port's cargo come from and go to."
- Vessel mix - distinct ships ever called, by segment: horizontal bars per segment, labelled "N ships · M DWT (M)". The widest bar is the dominant vessel class at the port - your first read on whether a port suits your tonnage.
- Top origin ports - laden imports: counts only arrivals where the ship came in laden (cargo on board); ballast/bunker stops are filtered out, so this is where this port's cargo actually comes from. Columns: Origin port (links to that port page), Country, Region, Laden arrivals, Avg transit (d). The heading carries an honest coverage-window label and a summary ("· N laden arrivals across M origin ports").
- Top destination ports - laden exports: the mirror image - ships that departed this port laden, grouped by the next port they called; ballast repositioning is excluded. Same column shape (Destination port, Country, Region, Laden departures, Avg transit (d)) plus window label and summary. Together the two tables map the port's real trade flows - invaluable for backhaul planning.
- Tonnage band - last 12 months: a table with DWT band, Arrivals, Ballast, Laden, Avg wait (d) - colour-coded so the ballast/laden split reads at a glance.
- Segment mix - last 12 months: the same five-column table grouped by Segment instead of DWT band. High laden share in your band/segment with low avg wait is the ideal load-port profile; high ballast share suggests a discharge-dominated port.
- Turnaround by tonnage - observed: a table with DWT band, Berth (d), Wait (d), Total (d), Legs and a Confidence dot - the median time a vessel of each tonnage class actually spends here on arrival, split into berth (load/discharge) and anchorage wait, measured from completed voyage legs. Where the 12-month tables above count how many ships call, this measures how long each class stays. The dot (green strong / amber moderate / grey thin) shows how much voyage history backs each band, and an "All classes" row pools every leg. These per-class turnaround days are exactly what each ship’s Forward Voyages timing uses for port time - a port that turns a Panamax in 2.5 days and a Supramax in 1.8 feeds those figures straight into the schedule. A berth shift or a bump out to anchorage mid-call - common where priority vessels (e.g. container ships) outrank a waiting bulker - is folded into the same call: the time at anchorage counts as that visit’s wait, not as a separate voyage, so the turnaround reflects the full door-to-door stay. They sharpen as more calls are recorded.
The Congestion board (/congestion) - today's anchorage queue, ranked
The Congestion board is a sortable, searchable league table of ports ranked by their live anchorage queue. The intro note is emphatic that everything here is live: the queue counts ships at anchorage right now, and the wait-day columns show how many days each still-waiting ship has already been there - the score will change tomorrow as ships arrive, berth or sail.
- The score: the live queue size, scaled up by how long the still-waiting ships have already been there - a bigger, longer-waiting queue scores higher. A ship simply moored at a berth is normal operation, not congestion, so berth figures are kept separate for context only. A colour key sits above the table: an amber swatch = "Anchorage - the congestion signal" and a blue swatch = "Berth - context only"; the matching columns carry a coloured top border (amber
.cg/ blue.bt). - Search + count: the top search box filters by port / LOCODE / country / region (300ms debounce), and the muted count reads "N ports · showing lo-hi (page P/Y)."
- Sortable columns: every header is clickable (cursor changes, hover turns accent-coloured) with an up/down arrow showing the active sort; clicking again flips direction. Columns: Code (links to the port page), Port, Country, Region; then the amber congestion group - Congestion (the score), At anchorage (the live queue), Now-waiting avg (d) (average days each still-waiting ship has already been there), Longest now (d) (the single ship waiting longest right now); then the blue berth group - Moored (ships at berth) and Avg berth (d); then Historic avg (d) and Legs.
- Cell colours & symbols: the Congestion cell is bold and colour-graded - pink ≥ 20, amber ≥ 6, grey below. At anchorage turns amber when > 0, grey when empty. When no ship is currently waiting, the avg/max wait cells show "-" (not 0) so the row doesn't read as zero days of wait. A small green b·N next to anchorage or moored counts = ships reported only via voyage records (position feed); hover the anchorage/berth cells for the live-vs-reported breakdown ("Live At Anchor: X · reported At Anchor: Y (deduped union)"). Counts dedupe across feeds per IMO.
- Historic avg (d): the all-time average anchorage wait from completed voyage legs at that port (shows "-" if none). It is not part of the live score - it's there so you can judge today's queue against the port's track record. Legs is the number of completed voyage legs underpinning that history (the sample size behind the historic figure).
How to read it: sort by Congestion (the default, descending) to see where queues are worst today; a high score driven by a large At anchorage with a modest Now-waiting avg is a fresh build-up, whereas a high Longest now flags a vessel that has been stuck a long time. Cross-check the Historic avg: a live queue far above the port's norm is the actionable signal - demurrage risk if you're heading in, and firming load-port rates if you're fixing out. Click any row to jump to that port's full detail page.
Network tab - operators, charterers & agents
The Network tab answers "who trades here". Top operators calling here is computed from the deep berth-call record - the owner / manager companies whose ships use this port most, with distinct ships, total calls and average size (like Cargo Routes, but for the fleets behind the traffic). Below it, Charterers and Agents are curated lists - this commercial layer is not in the AIS feed, so the operator maintains it; administrators add or remove entries inline.
Community-curated, admin-approved: any signed-in member can suggest a charterer or agent (with tonnage range and contact details - website, email, phone, MIC); it stays pending until an administrator approves it. Admins add entries directly and can remove any at will.
Charterers loading here - the market-circular layer
Inside the Network tab, the Charterers loading here panel lists the charterers (accounts) recorded loading cargo from this port in recent market circulars - the names behind the trade, which the AIS feed alone cannot tell you. It complements the AIS-derived operators (the fleets calling) and the curated contacts list with the commercial side: who fixes cargo out of this port. Names only - no broker contact details. The mapping is cleaned (real ports only, account aliases merged to one name, non-serious / breakbulk entries removed) and is a members-only view. It is reference intelligence, not a live AIS signal.
Port reference - max vessel size & facilities
The Now tab opens with a Port reference strip - the port's physical limits and facilities, drawn from a curated port-reference library and shown as quick chips. It tells you at a glance whether your ship physically fits, before you even look at the live traffic.
- Max vessel size - the largest stated deadweight, LOA and draft / depth the port can take. A ship drawing more than the stated draft cannot load to full there; one longer than the max LOA will not fit the berth.
- Water density - kg/m³ (about 1025 in salt water, ~1000 fresh). It changes how deep a given cargo weight sits, so it matters most where a port is draft-limited.
- Cranes - a green Shore cranes chip (with the SWL in tonnes when known) means the port can work a gearless ship; an amber Gearless - no shore cranes chip warns the vessel must use her own gear, so a gearless ship needs a geared berth or floating cranes.
- Bunkers, Pilotage compulsory and Anchorage chips flag fuel availability, whether a pilot is mandatory, and whether the port has a designated anchorage.
These are reference figures - the largest capability the port has stated - not a live reading, and the strip appears only for ports we hold a reference doc for (about two-thirds of the directory). Always confirm against the latest port circular or your agent before fixing. The panel joins to the port by its UN/LOCODE, the same key the rest of the page uses.
Agency fee (PDA) tab
For members, the port page has an Agency fee tab: drag a tonnage (DWT) slider to see the indicative agency fee for a typical ship of that size at this port - or its anchorage - this port's agency rate × a median size-coefficient × DWT. The fee tapers with size (it is not linear). Not vessel-specific; not a full proforma DA. It is an indicative agency-fee component, not a full proforma DA. The underlying rates are commercial and members-only; only the computed fee is shown.
Demurrage-at-Risk: pricing the wait
Turn “this port is busy” into a dollar figure. Every port page now carries a Demurrage risk tab that takes the port’s historical billable queue wait for a ship of your size and prices it as a tail - P50 (the median wait), P90 (the bad-day exposure) and P99 (worst case, indicative) - in your own demurrage rate and queue-free days. So instead of “47 ships waiting,” you get “at $18,000/day this call carries about $115k of P90 demurrage exposure” - a number you can negotiate laytime and free-time against.
What it prices, honestly. The figure covers the queue / anchorage waiting time only (the days a ship sits before berthing) - berth cargo-work time is deliberately excluded. It assumes WIBON / port terms where the anchorage wait is billable; under berth terms that wait is the owner’s time, so read the number as an upper bound. AIS waiting days are running calendar days, so under weather-working or SHEX laytime it is again an upper bound. No freight price is involved - only the wait distribution and your own rate.
Where the number comes from. P50/P90/P99 are read from the distribution of past waits for that port × DWT band, drawn from the same voyage history the turnaround card uses (so the DaR median lines up with it). For the handful of genuinely congested ports with deep queue history you get that port’s own tail; for a port with thin history the card clearly shows a band-typical reference instead - never a made-up port-specific number. This is the wait priced today; the more history the platform accrues, the sharper and better-proven the tail becomes.
Demurrage risk: the live queue beside the tail
Now with a live read of the queue forming right now. The Demurrage-risk tab shows the port’s current anchorage queue beside the historical tail: how many ships are waiting at anchor at this moment, how long they have already waited, and a coarse directional read - running hot, in line, or running light - against this port’s own normal wait. So a deep-but-fast-moving queue reads “64 waiting, but only ~1.4 days each vs ~6 days normal - running light,” while a backed-up port turns hot.
Deliberately honest about what it is. The live read is context, not a re-priced number: the P90 dollar figure stays the historical tail and is never inflated by the live queue. The queue count is port-wide (all sizes) while the tail is this port × size; the read is like-for-like (current already-waited vs the port’s own historical wait) so a normal queue reads normal, not hot. If the position feed goes quiet the live read switches off everywhere rather than show a stale “hot” - a manufactured live figure is worse than none. A self-scoring calibration of the queue against realised waits comes as the history deepens.
Demurrage risk: a tail that scores itself
The number now keeps its own score. Every night the Demurrage-at-Risk quote for each port × size class is frozen into an append-only record. As ships then actually complete their port calls, the realised wait is compared against the quote frozen before they arrived - strictly before, so no forecast is ever graded on history it had already seen. The card shows the result plainly: how often the P90 actually held across recent tail-risk calls (target: 90%), and - when it was exceeded - by how many days on average.
Honest by construction. The scorecard only counts calls where the port model genuinely priced queue risk (a port with a zero-wait history proves nothing); it needs both enough scored calls and enough distinct days of frozen quotes before it shows a percentage - until then the card simply says the calibration is accruing. Every quote is immutable once frozen: the record can deepen, it can never be rewritten. That growing frozen-forecast ledger is something a new entrant cannot reconstruct at any price - it only exists if you started freezing it when we did.