Salish Ops Intelligence   ← Live dashboard
Independent monitoring · data engineering · public records

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.

55.2%of Route 1 sailings overloaded in FY2025. That is 4,783 sailings that turned vehicles away
89.6%annual vehicle-deck utilization, three years running near 90%, winter Tuesdays included
−11.9ppon-time performance decline as saturation rose (84.3% in FY22 → 72.3% in FY24)
Route 1 by fiscal year, from BC Ferries' Annual Reports to the Commissioner (FY2022–FY2025). Overloads and utilization climb together while punctuality falls. FY2025 methodology excludes alternative service; FY2024 restated equivalent is 58.4%. BC Ferries · published

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.

Share of sailings that hit 100% vehicle-deck booking fill, per day since this system began collecting (live; updates as the archive grows). Tsawwassen corridors (Routes 1, 30, 9 both directions) vs the rest of the capacity-managed network. Booking fills understate true demand: walk-ups turned away never appear. observed · live

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.

Earnings (loss) from operations, FY2025, in $M, from the route statements BC Ferries files with its Commissioner. Route 1 is broken out of the majors; provincial fees shown where allocated. BC Ferries · published

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.

Actual FY2025 round trips as a percentage of each route's contractual minimum. Minor routes cluster at 98–104%, so the contract effectively sets their service. Route 1 runs 23% above a floor that stopped meaning anything years ago. contract + published actuals

"…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.

Arrival lateness of Tsawwassen–Southern Gulf Islands sailings through Sunday July 12, reconstructed from archived Current Conditions snapshots. Both vessels were late from their first sailings; with zero recovery slack the delay compounded until the midday peak passed. BC Ferries · published, archived by this system

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:

Observed berth-to-berth crossing times on the Nanaimo–Vancouver corridor, from AIS tracks captured by this system in July 2026. Different products (Hullo carries no vehicles), but for a foot passenger the comparison is real. AIS · observed

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:

Announced time minus AIS-observed berth event, minutes. Departures match to the sampling noise floor; arrivals are logged ~1.5 minutes after physical docking, which is conservative and in the customer's favour. One +18-minute outlier excluded: it predates continuous capture and is an artifact of my data, not theirs. AIS · observed vs published

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

DataSourceProvenance
Vessel positions, tracks, crossingsOwn receiver + AISHubobserved
Scheduled/actual times, booking fill, delaysbcferries.com conditions (archived 5-min)published
Utilization, overloads, OTP, per-route financesAnnual Reports to the Commissioner FY2022–25published
Service minimums, capacity clauseCoastal Ferry Services Contract (consolidated 2024)published
Fuel by routeBC Ferries FOI release, FY2020published
Weather, tides, road eventsOpen-Meteo, DFO, DriveBC, ECCCobserved/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:

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.