How to Publish a GTFS Feed (And What Could Break)
Publishing a GTFS feed is not the same as creating one. You can build a perfectly valid feed and still have it not appear in Google Maps a month later. The gap is "publishing" — the operational steps between "the zip exists on my laptop" and "Apple Maps shows my bus running on time."
This guide walks the five things that have to happen, in order, and the four ways each one breaks in production. It's written for a small-agency staffer or consultant publishing for the first time, or troubleshooting a feed that stopped working.
What "publishing a GTFS feed" actually means
There's no central GTFS registry that you submit to and get a checkmark. Publishing a GTFS feed means making the zip file available at a permanent public URL, then telling each downstream consumer where to find it. Each consumer fetches the file on its own schedule — daily, weekly, or whenever they feel like it.
The downstream consumers that matter:
- Mobility Database — the canonical open registry, maintained by MobilityData. Trip planners, researchers, and AI tools poll it. If your feed isn't in the Mobility Database, you're invisible to most of the ecosystem.
- Google Maps Transit — separate registration through Google's Transit Partners program. Approval can take weeks; once approved, Google fetches your feed on a schedule they set.
- Apple Maps Transit — separate registration with Apple, similar process.
- Transit App — picks up most feeds from the Mobility Database automatically; some agencies are added through direct outreach.
- OpenTripPlanner / regional trip planners — most operators of OTP-based regional planners watch the Mobility Database, but the larger ones have direct lists.
So "publishing" is really "host the file + register it in the Mobility Database + (optionally) directly register with Google and Apple."
The five things that have to happen
1. Your feed validates
A valid GTFS feed is one that passes the Canonical GTFS Validator maintained by MobilityData. The validator emits errors (blocking) and warnings (informational). For publishing, errors must be zero. Most warnings are fine.
This is where most first-time publishers get stuck. The validator output is a 200-page HTML report and the errors are not always obvious. The most common errors:
stop_timesreferencing atrip_idthat doesn't exist intrips.txttrip_idreferencing aservice_idthat doesn't exist incalendar.txtorcalendar_dates.txt- Timezone mismatch between
agency.txtandstop_times.txt(arrival times in local time but agency declared a different timezone) - Missing
feed_info.txtwith publisher name and version (Mobility Database requires this)
If you're using GTFS·X, validation is continuous — errors block export and surface inline, so you can't export a feed that won't pass the canonical validator. If you're building with Excel or a Python script, run the validator against your zip before doing anything else.
2. The zip lives at a permanent URL
Trip planners poll feeds at a URL on their own schedule. The URL has to:
- Resolve over HTTPS (HTTP-only is rejected by Google and increasingly by the Mobility Database)
- Return the same zip file (or a newer version) every time it's fetched
- Not require a login or a session cookie
- Not have a query string the consumer is expected to fill in (so
?token=abcschemes don't work) - Not 404 when the agency's website CMS gets reorganized
That last one is the slow killer. The most common reason a feed disappears from Google Maps is that the agency rebuilt its website, the URL pattern changed, and the old feed URL now 404s. The downstream consumer fetches, gets a 404, eventually marks the feed dead. The agency doesn't notice until a rider complains.
The right answer is to publish to a URL pattern that's outside the marketing site's CMS. Options:
- A dedicated subdomain you control (
gtfs.youragency.org) - A managed publishing service that gives you a stable URL (GTFS·X hosted publishing, Trillium, etc.)
- An S3 / Cloudflare R2 bucket with a public read policy
What doesn't work long-term: a URL under your main website's WordPress instance. The CMS will be reorganized in three years and the URL will break.
3. The feed is registered in the Mobility Database
The Mobility Database is at mobilitydatabase.org. Registration is free, takes about ten minutes, and is reviewed by the MobilityData team. You provide:
- The feed URL
- Agency name and contact
- Service area (state, country)
- License (most use CC0, some use CC-BY)
Once registered, your feed is fetched on a daily-to-weekly cadence and made available to anyone querying the database. This is the single most important step after validation. Skip it and you're invisible.
4. Direct registration with Google and Apple (if you want to be on their maps)
Google Maps Transit and Apple Maps Transit don't pull from the Mobility Database. Each requires direct application:
- Google: apply through Transit Partners. Review can take 4–12 weeks. Google will fetch the feed on its own schedule once approved.
- Apple: apply through Apple Maps Connect. Similar process and timeline.
Both are paperwork-heavy and one-time. Once you're in, you stay in until your feed breaks.
5. You set up a monitor that pings you when the feed dies
This is the step everyone skips and everyone regrets. Once your feed is live, you need an alert when:
- The URL returns anything other than HTTP 200 with a valid zip
- The validator starts emitting errors against the file
- The
feed_end_dateinfeed_info.txtfalls within 14 days (so you remember to extend service before the feed expires)
A free monitoring option is GTFS Monitor or the built-in monitoring in your publishing platform. GTFS·X hosted publishing includes feed-expiry and validation-failure alerts as part of the $500/yr managed publishing tier.
The four ways this breaks in production
After the feed is live, these are the four things that take it down. In rough order of frequency:
The feed expires. Every GTFS feed has a
feed_end_date. If your service runs continuously, you need to extend the calendar before the end date passes. When the feed expires, trip planners stop showing your service. The fix is calendar maintenance: build a 12-month-out service plan, set a recurring reminder 30 days before the end date.The URL breaks. Web team rebuilds the agency site, the feed URL moves, downstream consumers 404. Fix: get the URL onto a dedicated subdomain or managed publisher that the web team doesn't touch.
The HTTPS cert expires. If you're hosting the zip on your own infrastructure, your cert can expire. Most modern hosting auto-renews; legacy setups don't. Fix: move to a host with auto-renewing certs (every major cloud, most CMSs).
A schedule change breaks validation. Someone in scheduling adds a new route, a typo in a
route_idcreates a dangling reference, the next export fails validation but gets pushed anyway. Fix: validation gate in your publishing workflow. The export step should reject any feed that doesn't pass the canonical validator.
What to use to build and publish
This guide is tool-agnostic, but the publishing path it describes is what GTFS·X is designed to handle end-to-end. You can build a feed in GTFS·X with no signup, validate continuously as you author, and then either export the zip and host it yourself or use hosted publishing for a stable URL with monitoring built in.
If you'd rather build in Excel and self-host, RTAP's GTFS Builder is the standard free tool. If you want a managed service that handles all of the above for you, Trillium is the established option.
The choice depends on whether you want to own the tool or own the service.
FAQ
How long does it take to get a feed live on Google Maps? About 6–14 weeks from first submission to first rider seeing your bus, including 4–12 weeks of Google's review. Once approved, future updates show up within a few days.
Do I need a separate feed for each route or each mode?
No. One feed per agency is the standard. Multiple agencies can also share one feed using agency_id.
What's the difference between "publishing" and "hosting"? Hosting is making the zip file available at a URL. Publishing includes hosting plus registration in the Mobility Database and downstream trip planners.
Does my feed have to be updated daily? No. Update when your schedule changes. Most small agencies update 2–4 times per year (signal-driven, not calendar-driven). The feed file at the URL should always reflect current service.
Can I publish a feed without a website? Yes. The feed needs a public URL, but it doesn't need to live on your agency's marketing site. A bucket-and-CDN setup works, as does any of the managed publishing services.
Build and publish your GTFS feed at gtfsx.com — no signup required to start.