How container tracking data really moves between carriers, AIS and terminals, why statuses contradict, and how to monitor boxes without a spreadsheet.
Every forwarder I know has the same tab open somewhere: a spreadsheet with container numbers down the left, a column for "last known status", and a colour code that someone updates by hand after phoning the agent. It works until it doesn't, usually on the one shipment the customer is actually chasing. If you just want a quick answer right now, run the number through /tools/track. This article is about what's happening underneath, so the next status you see makes sense instead of raising more questions.
Container tracking isn't one feed. It's three different systems that don't always agree, stitched together by whoever's asking.
| Source | What it tells you | Typical lag | Where it breaks |
|---|---|---|---|
| Carrier event feeds (EDI/API) | Gate in/out, loaded, discharged, empty return | Can run hours behind the physical event | Depends entirely on the carrier's own system updating promptly |
| AIS vessel position | Where the ship actually is, right now | Near real time at sea, gaps in port | Tells you the vessel moved, not that your specific box moved with it |
| Terminal feeds | Yard location, gate activity, vessel ETA at that terminal | Varies by terminal operator | Only covers that one terminal, not the whole journey |
None of these three is lying to you. They're each describing a different slice of the same box, at a different moment, from a different system of record. A forwarder stitching these together manually is doing data reconciliation with a phone and a spreadsheet, every single day, for every live shipment.
This is the question that actually generates the support tickets, so it's worth being precise about it.
The event hasn't synced yet. The container was physically loaded. The carrier's internal system knows it. The API feed that your tracking page or portal reads from hasn't picked that up yet. You're both right, you're just reading the ship at different times.
You're looking at different legs. On a transhipment routing, the first carrier's feed stops being useful the moment the box leaves their vessel. If leg two is a different carrier, or the box moves onto a feeder service, you're now relying on a second feed that may use different event codes, different timestamps, and sometimes a different container number reference if it's been re-booked. Transhipment is where visibility consistently breaks down, and it's the single biggest source of "but it says something different on the carrier's own site" tickets.
Someone overwrote the live status with a document. This one is avoidable and worth checking in your own setup. If a shipment's milestones get populated from an uploaded document (a draft BL, a pre-advice, a manually keyed ETA) and then a live carrier update comes in later, the system needs to know which one wins. In CargoMode, booking data that's enriched directly from liner APIs is protected from being silently overwritten by a document upload. That sounds like a small detail until you've spent an afternoon figuring out why a confirmed vessel ETA reverted to a stale PDF date.
You don't need enterprise tracking infrastructure to get out of the spreadsheet. You need three things: a single list of active containers, a way to diff "last status" against "current status", and a trigger for when that diff matters.
Here's the shape of it, as a plain structure you can build in anything from a shared sheet to a proper workflow:
container_number, carrier, last_event_code, last_event_time,
last_checked_at, next_expected_event, alert_if_overdue_by
The field that does the actual work is alert_if_overdue_by. You're not trying to watch every box all the time, you're trying to get told when a box has gone quiet past its expected next event. A worked example, using your own numbers:
Active containers this month: A
Average time spent per manual check: B minutes
Checks done per container per week: C
Weekly hours spent just confirming status = (A × B × C) / 60
Run your own figures through that. For most small forwarding teams, the number is bigger than expected, because the checking happens in small five-minute increments scattered across the day, which never shows up as a single line item anyone questions.
The fix isn't more checking, it's checking by exception. Flag containers where:
Those three conditions catch almost everything a human spreadsheet-watcher would have caught anyway, just without needing a human watching continuously.
Before you escalate to the carrier or tell the customer something's gone missing, run through this in order:
Most "the system is wrong" moments are actually "the system is describing a different leg, a different timestamp, or a different source than the one you were expecting." Knowing which of those three it is turns a ten-minute investigation into a ten-second one.
If you're tracking containers by hand right now, start by replacing the lookup step. Put the container number into /tools/track and see the event history pulled directly rather than reconstructed from memory and a half-updated spreadsheet.
Join freight forwarders saving hours every week with CargoMode.
Start for free