“Design a transit app” is a niche but technically rich mobile-system-design prompt. Citymapper, Transit, Moovit, Apple Maps Transit are the references. The interview tests whether you can reason about the GTFS data model, real-time vehicle tracking, multi-modal trip planning, and the offline-first requirements of “I am underground and need to know when my train arrives.”
Clarify scope
- One city or multi-city?
- Just bus/rail or also bike-share, scooters, ride-share?
- Trip planning (point A to B) or just departure boards?
- Real-time arrivals or schedule-only?
- Pay-for-fare integration?
The GTFS data model
GTFS (General Transit Feed Specification) is the universal format for transit schedules:
- Routes (e.g., “1 train”)
- Stops (e.g., “59 St – Columbus Circle”)
- Trips (one run of a route on a day)
- Stop times (when each trip arrives at each stop)
- Calendar (which trips run on which days)
- Shapes (the geographic path of a route)
GTFS-realtime adds vehicle positions, trip updates (delays), and service alerts.
Schedule data: client or server?
- Static GTFS for a major city is 50–500 MB compressed
- Most apps cache the per-city schedule on device for offline lookup
- Server provides differential updates (rare changes, mostly weekly)
- Client computes “next arrivals at this stop” locally — needs offline
Real-time updates
- GTFS-realtime feeds delivered as protobuf over HTTP, polled every 30–60 sec
- Or WebSocket subscription for active trips/stops
- Vehicle positions (lat/lon) animated client-side between samples
- Trip updates: predicted arrival times that override the schedule
Trip planning
This is the algorithmically hardest part. Approaches:
- RAPTOR (Round-Based Public Transit Routing) — the modern standard
- CSA (Connection Scan Algorithm) — simpler, fast for fewer transfers
- Multi-modal: combine walking + transit + bike-share segments
Server typically runs the routing engine; client renders results. For offline, OTP (OpenTripPlanner) or pre-computed transit-graph data can be embedded.
Live navigation during a trip
- “You are on the 1 train, get off at 86 St in 3 stops”
- Watch presence: tap to confirm boarding
- Notifications: “Your stop is next”, “Get off here”
- Disruption alerts: “Your route is delayed; here is an alternative”
- Background location used sparingly to verify the user is on the predicted vehicle
Departure boards
- Per-stop, per-route board showing next 3–5 arrivals
- Refresh every 15–30 sec while screen is foregrounded
- Apple Watch complication shows next arrival from the saved stop
- Live Activity / Dynamic Island for active trips
Offline strategy
- Cache schedules per city
- Cache the trip plan when generated; works offline if no fresh real-time data
- Show “Last updated 5 min ago” indicator when stale
- Underground / no-signal: show schedule-based estimate as fallback
Map rendering
- Vector tiles (Mapbox, MapLibre) for base map
- Transit overlay rendered client-side from GTFS shapes
- Vehicle markers updated via GTFS-realtime positions
- Route highlighting on selected trip
Fare integration
- Mobile ticketing: app-purchased ticket scanned at gate
- OMNY / Clipper / Oyster: tap-to-pay using Apple Pay / Google Pay credentials
- Subscription / pass management with auto-renewal
Accessibility
- VoiceOver / TalkBack: announce next arrival times in natural language
- Wheelchair-accessible filtering for trip planning
- High-contrast mode for departure boards
- Audio alerts for upcoming stops
Battery considerations
- GPS only when the user is actively navigating; visit-based location otherwise
- Background fetch limited to active trip
- Reduce update frequency when app is backgrounded
Multi-city handling
- Detect user’s city via location and cached city footprints
- Download city schedule on first use; cache
- Switch active city when user crosses a boundary or manually selects
What separates senior from staff
Senior candidates draw the GTFS client/server split. Staff candidates discuss the trip-planning algorithm choice, offline-first design, and the multi-modal integration story. Principal candidates address the data-quality problem (transit agencies vary widely in feed reliability) and the operational reality of running 50+ city integrations.
Frequently Asked Questions
Should I write my own routing?
No. OpenTripPlanner, Navitia, or commercial APIs (HERE, TomTom) all do this well. Build the UX; rely on a routing engine for the heavy math.
What about agency-specific quirks?
Reality of transit data — the BART feed is different from the MTA feed in subtle ways. Have an abstraction layer that normalizes per-agency adapters. Plan for “this agency’s GTFS-realtime is unreliable” as a permanent state for some.
How do I handle Subway-specific nuances?
NY Subway has uptown/downtown with the same route name; some lines run different patterns at night. These are GTFS modeling questions; the data is there but the app must surface it correctly.