Skip to main content

Architectural overview

Vambora's backend follows Hexagonal (Ports & Adapters) with three pragmatic refinements: DDD-lite (bounded contexts, no full aggregate modeling), pragmatic CQRS (commands and queries split in code, single database), and event-driven ingestion (in-process pub/sub now, Redis later).

The full rationale lives in ADR-0001.

Bounded contexts

ContextResponsibility
trackingLive vehicle positions, GPS ingestion, current state
catalogStatic GTFS data: routes, stops, trips, schedules, agencies
routingMulti-modal itineraries, transfers, walking legs
predictionsETAs, headways, punctuality, derived signals
alertsUser-defined rules and notification dispatch
userDevice identity, preferences, favorites

Only tracking is implemented today. The rest are placeholders that will fill in across Phase 1 and beyond.

Dependency rule

domain → nothing (pure Python / pure Kotlin)
application → domain + ports
adapters → ports + third-party libraries

Code that ingests SPPO, persists to Postgres, calls Firebase, or talks to OpenTripPlanner all lives behind ports. Swapping any one of those touches only an adapter.