Measuring a Ferry System
I pointed an AIS antenna, four data loggers, and a hundred pages of regulatory filings at BC Ferries. The result is a continuous operational history that BC Ferries itself doesn't publish. It shows one of Canada's busiest ferry routes being rationed by queue while its fares underwrite the rest of the coast.
Why this exists
BC Ferries publishes scheduled sailings, annual statistics, and route-level financials, but it does not publish a continuous operational history. Live conditions overwrite themselves, service notices are deleted when a disruption ends, and per-sailing actual times exist for only 12 of 25 routes before scrolling away within a day. This project reconstructs that missing history. The underlying system is an operational intelligence platform: it ingests AIS movements, archives ephemeral operating data, derives berth-to-berth crossings for the routes with no published record, and validates its own observations against the operator's filings. This report is the first article written from that platform. The platform keeps collecting either way.
The system
Everything in this report rests on a monitoring stack I built over a weekend and left running: my own AIS receiver logging ship movements in the southern Strait of Georgia, pooled with the worldwide AISHub feed to cover the whole BC coast; a poller archiving BC Ferries' Current Conditions every five minutes: scheduled times, actual departures and arrivals, booking fill, delay announcements; and collectors for marine forecasts, road incidents, and service notices (BC Ferries deletes these when a disruption ends; mine keeps them). A derivation job converts raw vessel tracks into berth-to-berth crossings for the ~116 routes where BC Ferries publishes no actual times at all. That derivation is the technically hard part: AIS is a stream of raw position reports, not crossing records, so arrivals, departures, vessel identity, and terminal events all have to be inferred before a "crossing" exists at all.
On top of the live data sits the public record: five years of Annual Reports to the BC Ferries Commissioner (route-level finances, utilization, punctuality, and overloads), the Coastal Ferry Services Contract with the Province, an FOI release of per-route fuel consumption, and thirteen months of monthly traffic statistics. Every figure below is tagged with its provenance: AIS · observed means my antenna saw it; BC Ferries · published means it comes from the operator's own filings. One note on scope up front: the live observations here cover a single July week so far and grow daily; every multi-year claim in this report rests on the audited filings, not on my sample.
01Rationed by queue
"The ferries are always full" is a west-coast cliché. The filings make it a precise, multi-year fact. BC Ferries reports a metric called overloaded sailings, meaning sailings where at least one vehicle waiting at the terminal could not be accommodated. On Route 1, Tsawwassen–Swartz Bay, the flagship connection between Vancouver and Victoria, a majority of all sailings have been overloaded every year since fiscal 2023.
My own week of observation shows what an annual average of 90% means day to day: the booking system sells out the vehicle deck across the whole service day, not just at rush hours. On the Tsawwassen corridors, sailings routinely sell out the night before. In practice, access is allocated to those able to book earliest. Whether that is an equitable allocation mechanism is a policy question rather than an operational one.
02The profit engine that couldn't buy a boat
Route 1 isn't just the busiest route. Financially, it is the system. In fiscal 2025 it earned $80.0M from operations, which is 99% of the operating profit generated by all four major routes combined. The eighteen minor routes lost $145.6M from operations, recovering only 45 cents of each operating dollar from fares. The Province's ferry transportation fee covers $131M of that hole; the remaining $69M gap is carried by the regulated fare envelope, which in practice means Route 1's riders.
This is the documented design of the Coastal Ferry Act: profitable corridors and taxpayers jointly underwrite lifeline routes. Nothing scandalous, until you put it beside section 01: the customers funding the system are the ones being turned away at the booth. In March 2025 the BC Ferries Commissioner approved four replacement vessels for the corridor's 1960s–70s fleet but denied the fifth, the only ship that would have added capacity, calling it "neither essential nor affordable" and citing fare pressure. Those fares are substantially generated by the corridor whose capacity expansion was declined.
03A floor built for another decade
Service levels are governed by the Coastal Ferry Services Contract between BC Ferries and the Province. I parsed the minimum required round trips for all 25 designated routes out of the current consolidated contract and compared them with what BC Ferries actually sailed in FY2025.
"…the capacity provided on the Designated Ferry Route will be sufficient to carry the previous year's traffic."
— Coastal Ferry Services Contract, Schedule A, Appendix 1, clause 2(d). The contractual definition of adequate capacity is backward-looking by construction.That one clause explains the overload chart in section 01 better than any operational failure could: in a growing market, a previous-year capacity standard guarantees permanent under-supply. The contract precisely specifies the loss-making service the Province subsidizes, and is functionally silent about the saturated corridor that funds it.
04Anatomy of a saturated day
Annual averages hide how failure actually happens. On Sunday, July 12, the first full day this system was collecting, the Tsawwassen–Gulf Islands service came apart. The archive caught the whole sequence at five-minute resolution.
The day's first sailing arrived 43 minutes late. By 10:38 the compounding had reached +96 minutes. Both vessels on the route were affected. This wasn't a breakdown; it was a sold-out summer Sunday on a multi-stop route scheduled with no slack. BC Ferries posted "Sailing Delay" notices by midday and deleted them the moment the day ended; the stated cause was never published, but the conditions rule out weather (light winds all day) and single-vessel mechanical failure.
Under conservative assumptions (BC Ferries' own vehicle-occupancy figures, walk-ons excluded), the delays that Sunday represent roughly 371,000 person-minutes, about 6,200 passenger-hours of lost time.† A fleet with 90% annual utilization has no firebreaks; every peak day carries this tail risk.
† At a conventional $25/hour value of time that converts to roughly $155,000. The hours are the robust figure; the dollar conversion is a standard transport-economics convention, shown for scale.
05The competitor clock
Hullo, the private passenger-only fast ferry, runs downtown Nanaimo to downtown Vancouver. Their catamarans and BC Ferries' vessels are in the same AIS feed, so the same instrument measures both:
The corridor pressure shows up in BC Ferries' own books: Route 2 (Horseshoe Bay–Departure Bay) was the only major route to lose passengers in FY2025 (−64,495, −$1.15M) while every other major grew. Every foot passenger who switches frees vehicle deck nobody else can use. On a corridor where vehicle capacity is the binding constraint and new hulls are years away, shifting foot passengers to a mode built for them is the cheapest capacity available to BC Ferries, and it requires no capital approval. That is the case for partnership rather than rivalry: interline the ticketing and stop moving pedestrians on 358-car vessels.
06Auditing the operator's clock
Everything BC Ferries publishes about its own punctuality is self-reported. Because my system watches the same sailings by radio, it can check. I geofenced every terminal and compared BC Ferries' announced departure and arrival times against what the AIS tracks show, across 47 sailings with full coverage:
The audit passes. Announced departures are exact to the minute; announced arrivals slightly under-claim. That result matters twice over: it means the numbers in sections 01–04, all drawn from BC Ferries' own reporting, can be taken at face value, and it licenses trusting my AIS-derived record on the 116 routes where no official actuals exist to check.
07Methods, stack & caveats
Stack
Raspberry Pi 3B + RTL-SDR running AIS-catcher, feeding AISHub and MarineTraffic; Python collectors (stdlib only) on a home server polling AISHub (66s), BC Ferries conditions via the community API (5 min), DriveBC/Environment Canada/service notices (15 min); SQLite with WAL; a derivation job clustering tracks into berth events; and the live dashboard this page is part of. All of it is systemd-managed, reboot-proof, and has run unattended since day one.
Sources
| Data | Source | Provenance |
|---|---|---|
| Vessel positions, tracks, crossings | Own receiver + AISHub | observed |
| Scheduled/actual times, booking fill, delays | bcferries.com conditions (archived 5-min) | published |
| Utilization, overloads, OTP, per-route finances | Annual Reports to the Commissioner FY2022–25 | published |
| Service minimums, capacity clause | Coastal Ferry Services Contract (consolidated 2024) | published |
| Fuel by route | BC Ferries FOI release, FY2020 | published |
| Weather, tides, road events | Open-Meteo, DFO, DriveBC, ECCC | observed/official |
Caveats, stated plainly
· Booking fills understate demand: turned-away walk-ups never appear in any dataset, including BC Ferries' overload counts (which only count vehicles that showed up).
· Passenger-minute and dollar figures are estimates: 2.2 occupants/vehicle, walk-ons excluded, $25/hr value of time, approximate one-way fare equivalents. Assumptions are shown wherever the numbers are.
· My live observations cover one July week as of writing; the multi-year claims rest on the audited filings, not my one-week sample.
· AIS position sampling is ~66 seconds, so berth-event timing carries ±1 minute.
· I'm a fan of this ferry system and its crews. The critique here is aimed at a contract structure and a capital-approval framework, not the people sailing the ships.
What's next
The platform keeps collecting on its own. As coverage deepens, the same data supports analyses this report is too young for:
- Seasonal and day-of-week delay analysis
- Vessel utilization and rotation modelling
- Terminal congestion and berth-turnaround metrics
- Reliability trends by route, measured at the arrival berth
- Weather-normalized operational performance
- Capacity-planning scenarios grounded in observed demand
Each of these is a query against data already flowing, not a new build.
About the author
Rich Vickers is a data and software professional based in Delta, BC. This independent project combines AIS monitoring, public records, and software engineering to better understand ferry operations. It is not affiliated with BC Ferries.
Built and written by Rich Vickers, Delta BC. This report was generated from operational data collected continuously by the platform behind it — the live dashboard is at salish-ops.ca. Independent project, not affiliated with or endorsed by, British Columbia Ferry Services Inc. Data errors are mine; corrections welcome.