diff --git a/gtfs-realtime/best-practices/README.md b/gtfs-realtime/best-practices/README.md
new file mode 100644
index 00000000..5ef76007
--- /dev/null
+++ b/gtfs-realtime/best-practices/README.md
@@ -0,0 +1,19 @@
+# GTFS Realtime Best Practices
+
+These are recommended practices for describing real-time public transportation services in the [GTFS Realtime Reference](../spec/en/reference.md) format. These complement the explicit recommendations outlined in the GTFS Realtime Reference using the terms “recommend” or “should”. Although not mandatory, following these best practices can significantly improve the quality of the data and the overall experience for riders.
+These practices have been synthesized from the experience of the [GTFS Best Practices working group members](https://gtfs.org/schedule/best-practices/#gtfs-best-practices-working-group) and application-specific GTFS practice recommendations. See the [FAQ](https://gtfs.org/schedule/best-practices/#frequently-asked-questions-faq) for more information.
+
+---
+⚠️ **NOTE: The GTFS Realtime Best Practices are in the process of being merged into the [GTFS Realtime Reference](../spec/en/reference.md) (see [issue #396](https://github.com/google/transit/issues/396) and [issue #451](https://github.com/google/transit/issues/451) for more information).**
+**New Best Practices will be added directly to the GTFS Realtime Reference. If you'd like to suggest a new Best practice, you can:**
+- **look at the existing [list of outstanding issues and PRs](https://github.com/google/transit/issues/421). If your new Best Practice idea is referenced on this list, comment on the issue**
+- **[open a new issue](https://github.com/google/transit/issues/new/choose)**
+- **open a Pull Request following the [GTFS Realtime Amendment Process](https://gtfs.org/realtime/process/).**
+---
+
+## Documentation Structure
+
+The GTFS Realtime Best Practices are written in Markdown and are organized by Message and by use case.
+
+* `field_name`: The name of the GTFS Realtime field being described
+* `recommendations`: An array of the recommendations provided for each field_name
diff --git a/gtfs-realtime/best-practices/best-practices.md b/gtfs-realtime/best-practices/best-practices.md
new file mode 100644
index 00000000..4956a1b5
--- /dev/null
+++ b/gtfs-realtime/best-practices/best-practices.md
@@ -0,0 +1,163 @@
+# GTFS Realtime Best Practices
+
+## Introduction
+
+These are recommended practices for describing real-time public transportation information in the [GTFS Realtime Reference](https://gtfs.org/realtime/reference/) format. These complement the explicit recommendations outlined in the GTFS Realtime Reference using the terms “recommend” or “should”. Although not mandatory, following these best practices can significantly improve the quality of the data and the overall experience for riders.
+
+These practices have been synthesized from the experience of the [GTFS Best Practices working group](https://gtfs.org/schedule/best-practices/#gtfs-best-practices-working-group) members and [application-specific GTFS practice recommendations](http://www.transitwiki.org/TransitWiki/index.php/Best_practices_for_creating_GTFS).
+
+For further background, see the [Frequently Asked Questions](https://gtfs.org/schedule/best-practices/#frequently-asked-questions-faq).
+
+### Document Structure
+
+Recommended practices are organized into two primary sections
+
+* __[Practice Recommendations Organized by Message](#practice-recommendations-organized-by-message):__ Recommendations are organized by message and field in the same order described in the official GTFS Realtime reference.
+* __[Practice Recommendations Organized by Case](#practice-recommendations-organized-by-case):__ With particular cases, such as frequency-based service (vs. schedule-based service), practices may need to be applied across several messages and fields as well as the corresponding GTFS schedule data. Such recommendations are consolidated in this section.
+
+### Feed Publishing & General Practices
+
+* Feeds should be published at a public, permanent URL
+* The URL should be directly accessible without requiring a login to access the feed. If desired, API keys may be used but registration for API keys should be automated and available to all.
+* Maintain persistent identifiers (id fields) within a GTFS Realtime feed (e.g., FeedEntity.id, VehicleDescriptor.id, CarriageDetails.id) across feed iterations.
+* GTFS Realtime feeds should be refreshed at least once every 30 seconds, or whenever the information represented within the feed (position of a vehicle) changes, whichever is more frequent. VehiclePositions tend to change more frequently than other feed entities and should be updated as frequently as possible. If the content has not changed, the feed should be updated with a new `FeedHeader.timestamp` reflecting that the information is still relevant as of that timestamp.
+* Data within a GTFS Realtime feed should not be older than 90 seconds for Trip Updates and Vehicle Positions and not older than 10 minutes for Service Alerts. For example, even if a producer is continuously refreshing the `FeedHeader.timestamp` timestamp every 30 seconds, the age of VehiclePositions within that feed should not be older than 90 seconds.
+* The server hosting GTFS Realtime data should be reliable and consistently return validly-formatted protobuf-encoded responses. Fewer than 1% of responses should be invalid (protobuf errors or fetching errors).
+* The web-server hosting GTFS Realtime data should be configured to correctly report the file modification date (see HTTP/1.1 - Request for Comments 2616, under Section 14.29) so consumers can leverage the `If-Modified-Since` HTTP header. This saves producers and consumers bandwidth by avoiding transferring feed contents that haven't changed.
+* Feeds should provide protocol buffer-encoded feed content by default when queried via an HTTP request at the given URL - consumers should not need to define special HTTP accept headers to receive protocol-buffer encoded content.
+* Due to how protocol buffers encode [optional values](https://developers.google.com/protocol-buffers/docs/proto#optional), before reading data from a GTFS Realtime feed consumers should check for the presence of values using the protocol buffer-generated `hasX()` methods before using that value and should only use the value if `hasX()` is true (where `X` is the name of the field). If `hasX()` returns `false`, the default value for that field defined in the `gtfs-realtime.proto` value should be assumed. If the consumer uses the value without checking the `hasX()` method first, it may be reading default data that wasn't intentionally published by the producer.
+* Feeds should use HTTPS instead of HTTP (without encryption) to ensure feed integrity.
+* Feeds should cover the vast majority of trips included in the companion static GTFS dataset. In particular, it should include data for high-density and high-traffic city areas and busy routes.
+
+## Practice Recommendations Organized by Message
+
+### FeedHeader
+
+| Field Name | Recommendation |
+| --- | --- |
+| `gtfs_realtime_version` | Current version is "2.0". All GTFS Realtime feeds should be "2.0" or higher, as early version of GTFS Realtime did not require all fields needed to represent various transit situations adequately. |
+| `timestamp` | This timestamp should not decrease between two sequential feed iterations. |
+| | This timestamp value should always change if the feed contents change - the feed contents should not change without updating the header `timestamp`.
*Common mistakes* - If there are multiple instances of GTFS Realtime feed behind a load balancer, each instance may be pulling information from the realtime data source and publishing it to consumers slightly out of sync. If a GTFS Realtime consumer makes two back-to-back requests, and each request is served by a different GTFS Realtime feed instance, the same feed contents could potentially be returned to the consumer with different timestamps.
*Possible solution* - Producers should provide a `Last-Modified` HTTP header, and consumers should pass their most recent `If-Modified-Since` HTTP header to avoid receiving stale data.
*Possible solution* - If HTTP headers cannot be used, options such as sticky sessions can be used to ensure that each consumer is routed to the same producer server. |
+
+### FeedEntity
+
+All entities should only be removed from a GTFS Realtime feed when they are no longer relevant to users. Feeds are considered to be stateless, meaning that each feed reflects the entire real-time state of the transit system. If an entity is provided in one feed instance but dropped in a subsequent feed update, it should be assumed that there is no real-time information for that entity.
+
+| Field Name | Recommendation |
+| --- | --- |
+| `id` | Should be kept stable over the entire trip duration |
+
+### TripUpdate
+
+General guidelines for trip cancellations:
+
+* When canceling trips over a number of days, producers should provide TripUpdates referencing the given `trip_ids` and `start_dates` as `CANCELED` as well as an Alert with `NO_SERVICE` referencing the same `trip_ids` and `TimeRange` that can be shown to riders explaining the cancellation (e.g., detour).
+* If no stops in a trip will be visited, the trip should be `CANCELED` instead of having all `stop_time_updates` being marked as `SKIPPED`.
+
+| Field Name | Recommendation |
+| --- | --- |
+| `trip` | Refer to [message TripDescriptor](#TripDescriptor). |
+| | If separate `VehiclePosition` and `TripUpdate` feeds are provided, [TripDescriptor](#TripDescriptor) and [VehicleDescriptor](#VehicleDescriptor) ID values pairing should match between the two feeds.
For example, a `VehiclePosition` entity has `vehicle_id:A` and `trip_id:4`, then the corresponding `TripUpdate` entity should also have `vehicle_id:A` and `trip_id:4`. If any `TripUpdate` entity has `trip_id:4` and any `vehicle_id` other than 4, this is an error. |
+| `vehicle` | Refer to [message VehicleDescriptor](#VehicleDescriptor). |
+| | If separate `VehiclePosition` and `TripUpdate` feeds are provided, [TripDescriptor](#TripDescriptor) and [VehicleDescriptor](#VehicleDescriptor) ID values pairing should match between the two feeds.
For example, a `VehiclePosition` entity has `vehicle_id:A` and `trip_id:4`, then the corresponding `TripUpdate` entity should also have `vehicle_id:A` and `trip_id:4`. If any `TripUpdate` entity has `trip_id:4` and any `vehicle_id` other than 4, this is an error. |
+| `stop_time_update` | `stop_time_updates` for a given `trip_id` should be strictly ordered by increasing `stop_sequence` and no `stop_sequence` should be repeated. |
+| | While the trip is in progress, all `TripUpdates` should include at least one `stop_time_update` with a predicted arrival or departure time in the future. Note that the [GTFS Realtime spec](https://github.com/google/transit/blob/master/gtfs-realtime/spec/en/trip-updates.md#stop-time-updates) says that producers should not drop a past `StopTimeUpdate` if it refers to a stop with a scheduled arrival time in the future for the given trip (i.e. the vehicle has passed the stop ahead of schedule), as otherwise it will be concluded that there is no update for this stop. |
+| `timestamp` | Should reflect the time this prediction for this trip was updated. |
+| `delay` | `TripUpdate.delay` should represent schedule deviation, i.e., the observed past value for how ahead/behind schedule the vehicle is. Predictions for future stops should be provided through `StopTimeEvent.delay` or `StopTimeEvent.time`. |
+
+### TripDescriptor
+
+If separate `VehiclePosition` and `TripUpdate` feeds are provided, [TripDescriptor](#TripDescriptor) and [VehicleDescriptor](#VehicleDescriptor) ID values pairing should match between the two feeds.
+
+For example, a `VehiclePosition` entity has `vehicle_id:A` and `trip_id:4`, then the corresponding `TripUpdate` entity should also have `vehicle_id:A` and `trip_id:4`.
+
+| Field Name | Recommendation |
+| --- | --- |
+| `schedule_relationship` | The behavior of `ADDED` trips are unspecified and the use of this enumeration is not recommended. |
+
+### VehicleDescriptor
+
+If separate `VehiclePosition` and `TripUpdate` feeds are provided, [TripDescriptor](#TripDescriptor) and [VehicleDescriptor](#VehicleDescriptor) ID values pairing should match between the two feeds.
+
+For example, a `VehiclePosition` entity has `vehicle_id:A` and `trip_id:4`, then the corresponding `TripUpdate` entity should also have `vehicle_id:A` and `trip_id:4`.
+
+| Field Name | Recommendation |
+| --- | --- |
+| `id` | Should uniquely and stably identify a vehicle over the entire trip duration |
+
+### StopTimeUpdate
+
+| Field Name | Recommendation |
+| --- | --- |
+| `stop_sequence` | Provide `stop_sequence` whenever possible, as it unambiguously resolves to a GTFS stop time in `stop_times.txt` unlike `stop_id`, which can occur more than once in a trip (e.g., loop route). |
+| `arrival` | Arrival times between sequential stops should increase - they should not be the same or decrease. |
+| | Arrival `time` (specified in [StopTimeEvent](#StopTimeEvent)) should be before the departure `time` for the same stop if a layover or dwell time is expected - otherwise, arrival `time` should be be the same as departure `time`. |
+| `departure` | Departure times between sequential stops should increase - they should not be the same or decrease. |
+| | Departure `time` (specified in [StopTimeEvent](#StopTimeEvent)) should be the same as the arrival `time` for the same stop if no layover or dwell time is expected - otherwise, departure `time` should be after arrival `time` . |
+
+### StopTimeEvent
+
+| Field Name | Recommendation |
+| --- | --- |
+| `delay` | If only `delay` is provided in a `stop_time_update` `arrival` or `departure` (and not `time`), then the GTFS [`stop_times.txt`](https://gtfs.org/reference/static#stopstxt) should contain `arrival_times` and/or `departure_times` for these corresponding stops. A `delay` value in the realtime feed is meaningless unless you have a clock time to add it to in the GTFS `stop_times.txt` file. |
+
+### VehiclePosition
+
+Following are the recommended fields that should be included for a VehiclePostions feed to provide consumers with high-quality data (e.g., for generating predictions)
+
+| Field name | Notes |
+| --- | --- |
+| `entity.id` | Should be kept stable over the entire trip duration
+| `vehicle.timestamp` | Providing the timestamp at which vehicle position was measured is strongly recommended. Otherwise, consumers must use the message timestamp, which can have misleading results for riders when the last message was updated more frequently than the individual position.
+| `vehicle.vehicle.id` | Should uniquely and stably identify a vehicle over the entire trip duration |
+
+### Position
+
+The vehicle position should be within 200 meters of the GTFS `shapes.txt` data for the current trip unless there is an alert with the effect of `DETOUR` for this `trip_id`.
+
+### Alert
+
+General guidelines for alerts:
+
+* When `trip_id` and `start_time` are within `exact_time=1` interval, `start_time` should be later than the beginning of the interval by an exact multiple of `headway_secs`.
+* When canceling trips over a number of days, producers should provide TripUpdates referencing the given `trip_ids` and `start_dates` as `CANCELED` as well as an Alert with `NO_SERVICE` referencing the same `trip_ids` and `TimeRange` that can be shown to riders explaining the cancellation (e.g., detour).
+* If an alert affects all stops on a line, use a line-based alert instead of a stop-based alert. Do not apply the alert to every stop of the line.
+* While there is no character limit for service alerts, transit riders will often be viewing alerts on mobile devices. Please be concise.
+
+| Field Name | Recommendation |
+| --- | --- |
+| `description_text` | Use line breaks to make your service alert easier to read. |
+
+
+## Practice Recommendations Organized by Use Case
+
+### Frequency-based trips
+
+A frequency-based trip does not follow a fixed schedule but attempts to maintain predetermined headways. These trips are denoted in [GTFS frequency.txt](https://gtfs.org/reference/static/#frequenciestxt) by setting `exact_times=0` or omitting the `exact_times` field (note that `exact_times=1` trips are *NOT* frequency-based trips - `frequencies.txt` with `exact_times=1` is simply used as a convenience method for storing schedule-based trips in a more compact manner). There are several best practices to keep in mind when constructing GTFS Realtime feeds for frequency-based trips.
+
+* In [TripUpdate.StopTimeUpdate](#StopTimeUpdate), the [StopTimeEvent](#StopTimeEvent) for `arrival` and `departure` should not contain `delay` because frequency-based trips do not follow a fixed schedule. Instead, `time` should be provided to indicate arrival/departure predictions.
+
+* As required by the spec, when describing `trip` in [TripUpdate](#TripUpdate) or [VehiclePosition](#VehiclePosition) by using [TripDescriptor](#TripDescriptor), all of `trip_id`, `start_time`, and `start_date` must be provided. Additionally, `schedule_relationship` should be `UNSCHEDULED`.
+ (e.g., re-enforcement trips).
+
+ ## About This Document
+
+### Objectives
+
+The objectives of these GTFS Best Practices are:
+
+* Support greater interoperability of transit data
+* Improve end-user customer experience in public transportation apps
+* Make it easier for software developers to deploy and scale applications, products, and services
+* Facilitate the use of GTFS in various application categories (beyond its original focus on trip planning)
+
+### Contributing
+New Best Practices are now being added directly into the [spec](https://gtfs.org/schedule/reference/) in order to gradually consolidate both documents.
+If you'd like to suggest a new best practice, please go to the [GTFS Reference GitHub repository](https://github.com/google/transit/), [open an issue](https://github.com/google/transit/issues/new/choose) or create a Pull Request, or contact [specifications@mobilitydata.org](mailto:specifications@mobilitydata.org).
+
+### Linking to This Document
+
+Please link here in order to provide feed producers with guidance for correct formation of GTFS Realtime data. Each individual recommendation has an anchor link. Click the recommendation to get the URL for the in-page anchor link.
+
+If a GTFS Realtime-consuming application makes requirements or recommendations for GTFS Realtime data practices that are not described here, it is recommended to publish a document with those requirements or recommendations to supplement these common best practices.
+
diff --git a/gtfs/README.md b/gtfs/README.md
index 7f67b9b1..1ef4e77c 100644
--- a/gtfs/README.md
+++ b/gtfs/README.md
@@ -1,5 +1,6 @@
-This directory contains GTFS Specification and documentation.
+This directory contains the official General Transit Feed Specification (GTFS) Schedule reference documentation.
### Quick links
-- [Documentation](spec/en)
+- [GTFS Reference](spec/en)
+- [GTFS Best Practices](best-practices)
- [How to change the specification?](CHANGES.md)
diff --git a/gtfs/best-practices/README.md b/gtfs/best-practices/README.md
new file mode 100644
index 00000000..d991f849
--- /dev/null
+++ b/gtfs/best-practices/README.md
@@ -0,0 +1,21 @@
+# GTFS Schedule Best Practices
+
+These are recommended practices for describing public transportation services in the [GTFS Schedule Reference](../spec/en/reference.md) format. These complement the explicit recommendations outlined in the GTFS Schedule Reference using the terms “recommend” or “should”. Although not mandatory, following these best practices can significantly improve the quality of the data and the overall experience for riders.
+
+These practices have been synthesized from the experience of the [GTFS Best Practices working group members](https://gtfs.org/schedule/best-practices/#gtfs-best-practices-working-group) and application-specific GTFS practice recommendations. See the [FAQ](https://gtfs.org/schedule/best-practices/#frequently-asked-questions-faq) for more information.
+
+---
+⚠️ **NOTE: The GTFS Schedule Best Practices are in the process of being merged into the [GTFS Schedule Reference](../spec/en/reference.md) (see [issue #396](https://github.com/google/transit/issues/396) and [issue #451](https://github.com/google/transit/issues/451) for more information).**
+**New Best Practices will be added directly to the GTFS Realtime Reference. If you'd like to suggest a new Best practice, you can:**
+- **look at the existing [list of outstanding issues and PRs](https://github.com/google/transit/issues/421). If your new Best Practice idea is referenced on this list, comment on the issue**
+- **[open a new issue](https://github.com/google/transit/issues/new/choose)**
+- **open a Pull Request following the [GTFS Schedule Spec Amendment Process](https://gtfs.org/schedule/process/).**
+---
+
+
+## Documentation Structure
+
+The GTFS Schedule Best Practices are written in Markdown and are organized by Message and by use case.
+
+* `field_name`: The name of the GTFS Schedule field being described
+* `recommendations`: An array of the recommendations provided for each field_name
diff --git a/gtfs/best-practices/best-practices.md b/gtfs/best-practices/best-practices.md
new file mode 100644
index 00000000..011b35db
--- /dev/null
+++ b/gtfs/best-practices/best-practices.md
@@ -0,0 +1,300 @@
+# GTFS Schedule Best Practices
+
+These are recommended practices for describing public transportation services in the [GTFS Schedule Reference](https://gtfs.org/schedule/reference/) format. These complement the explicit recommendations outlined in the GTFS Schedule Reference using the terms “recommend” or “should”. Although not mandatory, following these best practices can significantly improve the quality of the data and the overall experience for riders.
+
+These practices have been synthesized from the experience of the [GTFS Best Practices working group](#gtfs-best-practices-working-group) members and [application-specific GTFS practice recommendations](http://www.transitwiki.org/TransitWiki/index.php/Best_practices_for_creating_GTFS).
+
+For further background, see the [Frequently Asked Questions](#frequently-asked-questions-faq).
+
+## Document Structure
+
+Practices are organized into two primary sections:
+
+* __[Practice Recommendations Organized by File](#practice-recommendations-organized-by-file):__ Recommendations are organized by file and field in the GTFS to facilitate mapping practices back to the official GTFS reference.
+* __[Practice Recommendations Organized by Case](#practice-recommendations-organized-by-case):__ With particular cases, such as loop routes, practices may need to be applied across several files and fields. Such recommendations are consolidated in this section.
+
+## Practice Recommendations Organized by File
+
+This section shows practices organized by file and field, aligning with the [GTFS reference](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md).
+
+### agency.txt
+
+| Field Name | Recommendation |
+| --- | --- |
+| `agency_phone` | Should be included unless no such customer service phone exists. |
+| `agency_email` | Should be included unless no such customer service email exists. |
+| `agency_fare_url` | Should be included unless the agency is fully fare-free. |
+
+__Examples:__
+
+- Bus services are run by several small bus agencies. But there is one big agency that is responsible for scheduling and ticketing and from a user’s perspective responsible for the bus services.The one big agency should be defined as agency within the feed. Even if the data is split internally by different small bus operators there should only be one agency defined in the feed.
+
+- The feed provider runs the ticketing portal, but there are different agencies that actually operate the services and are known by users to be responsible. The agencies actually operating the services should be defined as agencies within the feed.
+
+### stops.txt
+
+| Field Name | Recommendation |
+| --- | --- |
+| `stop_name` | When there is not a published stop name, follow consistent stop naming conventions throughout the feed. | |
+| | By default, `stop_name` should not contain generic or redundant words like “Station” or “Stop”, but some edge cases are allowed.
When it is actually part of the name (Union Station, Central Station
When the `stop_name` is too generic (such as if it is the name of the city). “Station”, “Terminal”, or other words make the meaning clear.
|
+| `stop_lat` & `stop_lon` | Stop locations should be as accurate possible. Stop locations should have an error of __no more__ than four meters when compared to the actual stop position. |
+| | Stop locations should be placed very near to the pedestrian right of way where a passenger will board (i.e. correct side of the street). |
+| | If a stop location is shared across separate data feeds (i.e. two agencies use exactly the same stop / boarding facility), indicate the stop is shared by using the exact same `stop_lat` and `stop_lon` for both stops. |
+| `parent_station` & `location_type` | Many stations or terminals have multiple boarding facilities (depending on mode, they might be called a bus bay, platform, wharf, gate, or another term). In such cases, feed producers should describe stations, boarding facilities (also called child stops), and their relation.
The station or terminal should be defined as a record in `stops.txt` with `location_type = 1`.
Each boarding facility should be defined as a stop with `location_type = 0`. The `parent_station` field should reference the `stop_id` of the station the boarding facility is in.
|
+| | When naming the station and child stops, set names that are well-recognized by riders, and can help riders to identify the station and boarding facility (bus bay, platform, wharf, gate, etc.).
Parent Station Name
Child Stop Name
Chicago Union Station
Chicago Union Station Platform 19
San Francisco Ferry Building Terminal
San Francisco Ferry Building Terminal Gate E
Downtown Transit Center
Downtown Transit Center Bay B
|
+
+### routes.txt
+
+| Field Name | Recommendation |
+| --- | --- |
+| `route_long_name` | The definition from Specification reference: This name is generally more descriptive than the route_short_name and will often include the route's destination or stop. At least one of route_short_name or route_long_name must be specified, or potentially both if appropriate. If the route does not have a long name, please specify a route_short_name and use an empty string as the value for this field. Examples of types of long names are below:
+| | `route_long_name` should not contain the `route_short_name`. |
+| | Include the full designation including a service identity when populating `route_long_name`. Examples:
Service Identity
Recommendation
Examples
"MAX Light Rail" TriMet, in Portland, Oregon
The route_long_name should include the brand (MAX) and the specific route designation
"MAX Red Line" "MAX Blue Line"
"Rapid Ride" ABQ Ride, in Albuquerque, New Mexico
The route_long_name should include the brand (Rapid Ride) and the specific route designation
"Rapid Ride Red Line" "Rapid Ride Blue Line"
+| `route_id` | All trips on a given named route should reference the same `route_id`.
Different directions of a route should not be separated into different `route_id` values.
Different spans of operation of a route should not be separated into different `route_id` values. i.e. do not create different records in `routes.txt` for “Downtown AM” and “Downtown PM” services).
|
+| | If a route group includes distinctly named branches (e.g. 1A and 1B), follow recommendations in the route [branches](#branches) case to determine `route_short_name` and `route_long_name`. |
+| `route_color` & `route_text_color` | Should be consistent with signage and printed and online customer information (and thus not included if they do not exist in other places). |
+
+### trips.txt
+
+* __See special case for loop routes:__ Loop routes are cases where trips start and end at the same stop, as opposed to linear routes, which have two distinct termini. Loop routes must be described following specific practices. [See Loop route case.](#loop-routes)
+* __See special case for lasso routes:__ Lasso routes are a hybrid of linear and loop geometries, in which vehicles travel on a loop for only a portion of the route. Lasso routes must be described following specific practices. [See Lasso route case.](#lasso-routes)
+
+| Field Name | Recommendation |
+| --- | --- |
+| `trip_headsign` | Do not provide route names (matching `route_short_name` and `route_long_name`) in the `trip_headsign` or `stop_headsign` fields. |
+| | Should contain destination, direction, and/or other trip designation text shown on the headsign of the vehicle which may be used to distinguish amongst trips in a route. Consistency with direction information shown on the vehicle is the primary and overriding goal for determining headsigns supplied in GTFS datasets. Other information should be included only if it does not compromise this primary goal. If headsigns change during a trip, override `trip_headsign` with `stop_times.stop_headsign`. Below are recommendations for some possible cases: |
+| |
Route Description
Recommendation
2A. Destination-only
Provide the terminus destination. e.g. "Transit Center", “Portland City Center”, or “Jantzen Beach”>
2B. Destinations with waypoints
<destination> via <waypoint> “Highgate via Charing Cross”. If waypoint(s) are removed from the headsign show to passengers after the vehicle passes those waypoints, use stop_times.stop_headsign to set an updated headsign.>
2C. Regional placename with local stops
If there will be multiple stops inside the city or borough of destination, use stop_times.stop_headsign once reaching the destination city.>
2D. Direction-only
Indicate using terms such as “Northbound”, “Inbound”, “Clockwise,” or similar directions.>
2E. Direction with destination
<direction> to <terminus name> e.g. “Southbound to San Jose”>
2F. Direction with destination and waypoints
<direction> via <waypoint> to <destination> (“Northbound via Charing Cross to Highgate”).>
|
+| | Do not begin a headsign with the words “To” or “Towards”. |
+| `direction_id` | Use values 0 and 1 consistently throughout the dataset. i.e.
If 1 = Outbound on the Red route, then 1 = Outbound on the Green route
If 1 = Northbound on Route X, then 1 = Northbound on Route Y
If 1 = clockwise on Route X then 1 = clockwise on Route Y
|
+| `bikes_allowed` | For ferry trips, be explicit about bikes being allowed (or not), as avoiding ferry trips due to missing data usually leads to big detours. |
+
+### stop_times.txt
+
+Loop routes: Loop routes require special `stop_times` considerations. (See: [Loop route case](#loop-routes))
+
+| Field Name | Recommendation |
+| --- | --- |
+| `pickup_type` & `drop_off_type` | Non-revenue (deadhead) trips that do not provide passenger service should be marked with `pickup_type` and `drop_off_type` value of `1` for all `stop_times` rows.
+| | On revenue trips, internal “timing points” for monitoring operational performance and other places such as garages that a passenger cannot board should be marked with `pickup_type = 1` (no pickup available) and `drop_off_type = 1` (no drop off available). |
+| `arrival_time` & `departure_time` | `arrival_time` and `departure_time` fields should specify time values whenever possible, including non-binding estimated or interpolated times between timepoints. |
+| `stop_headsign` | In general, headsign values should also correspond to signs in the stations.
In the cases below, “Southbound” would mislead customers because it is not used in the station signs.
+| |
In NYC, for the 2 going Southbound:
For stop_times.txt rows:
Use stop_headsign value:
Until Manhattan is Reached
Manhattan & Brooklyn
Until Downtown is Reached
Downtown & Brooklyn
Until Brooklyn is Reached
Brooklyn
Once Brooklyn is Reached
Brooklyn (New Lots Av)
|
+| |
In Boston, for the Red Line going Southbound, for the Braintree branch:
For stop_times.txt rows:
Use stop_headsign value:
Until Downtown is Reached
Inbound to Braintree
Once Downtown is Reached
Braintree
After Downtown
Outbound to Braintree
|
+
+### calendar.txt
+
+| Field Name | Recommendation |
+| --- | --- |
+| All Fields | Including a `calendar.service_name` field can also increase the human readability of GTFS, although this is not adopted in the spec. |
+
+### calendar_dates.txt
+
+| Field Name | Recommendation |
+| --- | --- |
+| All Fields | Including a `calendar.service_name` field can also increase the human readability of GTFS, although this is not adopted in the spec.|
+
+### fare_attributes.txt
+
+| Field Name | Recommendation |
+| --- | --- |
+| | If a fare system cannot be accurately modeled, avoid further confusion and leave it blank. |
+| | Include fares (`fare_attributes.txt` and `fare_rules.txt`) and model them as accurately as possible. In edge cases where fares cannot be accurately modeled, the fare should be represented as more expensive rather than less expensive so customers will not attempt to board with insufficient fare. If the vast majority of fares cannot be modeled correctly, do not include fare information in the feed. |
+
+### fare_rules.txt
+
+| Field Name | Recommendation |
+| --- | --- |
+| All Fields | If a fare system cannot be accurately modeled, avoid further confusion and leave it blank. |
+| | Include fares (`fare_attributes.txt` and `fare_rules.txt`) and model them as accurately as possible. In edge cases where fares cannot be accurately modeled, the fare should be represented as more expensive rather than less expensive so customers will not attempt to board with insufficient fare. If the vast majority of fares cannot be modeled correctly, do not include fare information in the feed. |
+
+### shapes.txt
+
+| Field Name | Recommendation |
+| --- | --- |
+| All Fields | Ideally, for alignments that are shared (i.e. in a case where Routes 1 and 2 operate on the same segment of roadway or track) then the shared portion of alignment should match exactly. This helps to facilitate high-quality transit cartography.
+| | Alignments should follow the centerline of the right of way on which the vehicle travels. This could be either the centerline of the street if there are no designated lanes, or the centerline of the side of the roadway that travels in the direction the vehicle moves.
Alignments should not “jag” to a curb stop, platform, or boarding location. |
+| `shape_dist_traveled` | The `shape_dist_traveled` field allows the agency to specify exactly how the stops in the `stop_times.txt` file fit into their respective shape. A common value to use for the `shape_dist_traveled` field is the distance from the beginning of the shape as traveled by the vehicle (think something like an odometer reading).
Route alignments (in `shapes.txt`) should be within 100 meters of stop locations which a trip serves.
Simplify alignments so that shapes.txt does not contain extraneous points (i.e. remove extra points on straight-line segments; see discussion of line simplification problem).
+
+### frequencies.txt
+
+| Field Name | Recommendation |
+| --- | --- |
+| All Fields | Actual stop times are ignored for trips referenced by `frequencies.txt`; only travel time intervals between stops are significant for frequency-based trips. For clarity/human readability, it is recommended that the first stop time of a trip referenced in `frequencies.txt` should begin at 00:00:00 (first `arrival_time` value of 00:00:00). |
+| `block_id` | Can be provided for frequency-based trips. |
+
+### transfers.txt
+
+`transfers.transfer_type` can be one of four values [defined in the GTFS](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md/#transferstxt). These `transfer_type` definitions are quoted from the GTFS Specification below, _in italics_, with additional practice recommendations.
+
+| Field Name | Recommendation |
+| --- | --- |
+| `transfer_type` | 0 or (empty): This is a recommended transfer point between routes. If there are multiple transfer opportunities that include a superior option (i.e. a transit center with additional amenities or a station with adjacent or connected boarding facilities/platforms), specify a recommended transfer point. |
+| | 1: This is a timed transfer point between two routes. The departing vehicle is expected to wait for the arriving one, with sufficient time for a passenger to transfer between routes. This transfer type overrides a required interval to reliably make transfers. As an example, Google Maps assumes that passengers need 3 minutes to safely make a transfer. Other applications may assume other defaults. |
+| | 2: This transfer requires a minimum amount of time between arrival and departure to ensure a connection. The time required to transfer is specified by min_transfer_time. Specify minimum transfer time if there are obstructions or other factors which increase the time to travel between stops. |
+| | 3: Transfers are not possible between routes at this location. Specify this value if transfers are not possible because of physical barriers, or if they are made unsafe or complicated by difficult road crossings or gaps in the pedestrian network. |
+| | If in-seat (block) transfers are allowed between trips, then the last stop of the arriving trip must be the same as the first stop of the departing trip. |
+
+
+## Practice Recommendations Organized by Case
+
+This section covers particular cases with implications across files and fields.
+
+### Loop Routes
+
+On loop routes, vehicles’ trips begin and end at the same location (sometimes a transit or transfer center). Vehicles usually operate continuously and allow passengers to stay onboard as the vehicle continues its loop.
+
+
+
+Headsigns recommendations should therefore be applied in order to show riders the direction in which the vehicle is going.
+
+To indicate the changing direction of travel, provide `stop_headsigns` in the `stop_times.txt` file. The `stop_headsign` describes the direction for trips departing from the stop for which it's defined. Adding `stop_headsigns` to each stop of a trip allows you to change the headsign information along a trip.
+
+Don’t define one single circular trip in the stop_times.txt file for a route that operates between two endpoints (such as when the same bus goes back and forth). Instead, split the trip into two separate trip directions.
+
+__Examples of circular trip modeling:__
+
+- Circular trip with changing headsign for each stop
+
+| trip_id | arrival_time | departure_time | stop_id | stop_sequence | stop_headsign |
+|---------|--------------|----------------|---------|---------------|---------------|
+| trip_1 | 06:10:00 | 06:10:00 | stop_A | 1 | "B" |
+| trip_1 | 06:15:00 | 06:15:00 | stop_B | 2 | "C" |
+| trip_1 | 06:20:00 | 06:20:00 | stop_C | 3 | "D" |
+| trip_1 | 06:25:00 | 06:25:00 | stop_D | 4 | "E" |
+| trip_1 | 06:30:00 | 06:30:00 | stop_E | 5 | "A" |
+| trip_1 | 06:35:00 | 06:35:00 | stop_A | 6 | "" |
+
+- Circular trip with two headsigns
+
+| trip_id | arrival_time | departure_time | stop_id | stop_sequence | stop_headsign |
+|---------|--------------|----------------|---------|---------------|---------------|
+| trip_1 | 06:10:00 | 06:10:00 | stop_A | 1 | "outbound" |
+| trip_1 | 06:15:00 | 06:15:00 | stop_B | 2 | "outbound" |
+| trip_1 | 06:20:00 | 06:20:00 | stop_C | 3 | "outbound" |
+| trip_1 | 06:25:00 | 06:25:00 | stop_D | 4 | "inbound" |
+| trip_1 | 06:30:00 | 06:30:00 | stop_E | 5 | "inbound" |
+| trip_1 | 06:35:00 | 06:35:00 | stop_F | 6 | "inbound" |
+| trip_1 | 06:40:00 | 06:40:00 | stop_A | 7 | "" |
+
+| Field Name | Recommendation |
+| --- | --- |
+| `trips.trip_id `| Model the complete round-trip for the loop with a single trip. |
+| `stop_times.stop_id` | Include the first/last stop twice in `stop_times.txt` for the trip that is a loop. Example below. Often, a loop route may include first and last trips that do not travel the entire loop. Include these trips as well.
trip_id
stop_id
stop_sequence
9000
101
1
9000
102
2
9000
103
3
9000
101
4
|
+| `trips.direction_id` | If loop operates in opposite directions (i.e. clockwise and counterclockwise), then designate `direction_id` as `0` or `1`. |
+| `trips.block_id` | Indicate continuous loop trips with the same `block_id`. |
+
+### Lasso Routes
+
+Lasso routes combine aspects of a loop route and directional route.
+
+
+
+| Examples: |
+| -------- |
+| Subway Routes ([Chicago](https://www.transitchicago.com/assets/1/6/ctamap_Lsystem.pdf)) |
+| Bus Suburb to Downtown Routes ([St. Albert](https://stalbert.ca/uploads/PDF-infosheets/RideGuide-201-207_Revised_Oct_2017.pdf) or [Edmonton](http://webdocs.edmonton.ca/transit/route_schedules_and_maps/future/RT039.pdf)) |
+| CTA Brown Line ([CTA Website](http://www.transitchicago.com/brownline/) and [TransitFeeds](https://transitfeeds.com/p/chicago-transit-authority/165/latest/route/Brn)) |
+
+| Field Name | Recommendation |
+| --- | --- |
+| `trips.trip_id` | The full extent of a “vehicle round-trip” (see illustration [above](#lasso-route-fig)) consists of travel from A to B to B and back to A. An entire vehicle round-trip may be expressed by:
A __single__ `trip_id` value/record in `trips.txt`
__Multiple__ `trip_id` values/records in `trips.txt`, with continuous travel indicated by `block_id`.
|
+| `stop_times.stop_headsign` | The stops along the A-B section will be passed through in both directions. `stop_headsign` facilitates distinguishing travel direction. Therefore, providing `stop_headsign` is recommended for these trips.example_table:
+| `trip.trip_headsign` | The trip headsign should be a global description of the trip, like displayed in the schedules. Could be “Linden to Linden via Loop” (Chicago example), or “A to A via B” (generic example). |
+
+### Branches
+
+Some routes may include branches. Alignment and stops are shared amongst these branches, but each also serves distinct stops and alignment sections. The relationship among branches may be indicated by route name(s), headsigns, and trip short name using the further guidelines below.
+
+
+
+| Field Name | Recommendation |
+| --- | --- |
+| All Fields | In naming branch routes, it is recommended to follow other passenger information materials. Below are descriptions and examples of two cases: |
+| | If timetables and on-street signage represent two distinctly named routes (e.g. 1A and 1B), then present this as such in the GTFS, using the `route_short_name` and/or `route_long_name` fields. Example: GoDurham Transit [routes 2, 2A, and 2B](https://gotriangle.org/sites/default/files/brochure/godurham-route2-2a-2b_1.pdf) share a common alignment throughout the majority of the route, but they vary in several different aspects.
Route 2 is core service, running most hours.
Route 2 includes a deviation on Main Street nights, Sundays, and holidays.
Routes 2A and 2B operate daytime hours Monday through Saturday.
Route 2B serves additional stops in a deviation of the shared alignment path.
|
+| | If agency-provided information describes branches as the same named route, then utilize the `trips.trip_headsign`, `stop_times.stop_headsign`, and/or `trips.trip_short_name` fields. Example: GoTriangle [route 300](https://gotriangle.org/sites/default/files/route_300_v.1.19.pdf) travels to different locations depending on the time of day. During peak commuter hours extra legs are added onto the standard route to accommodate workers entering and leaving the city. |
+
+## Frequently Asked Questions (FAQ)
+
+### Why are these GTFS Best Practices important?
+
+The objectives of GTFS Best Practices are:
+
+* To improve end-user customer experience in public transportation apps
+* Support broad data interoperability to make it easier for software developers to deploy and scale applications, products, and services
+* Facilitate the use of GTFS in various application categories (beyond its original focus on trip planning)
+
+Without coordinated GTFS Best Practices, various GTFS-consuming applications may establish requirements and expectations in an uncoordinated way, which leads to diverging requirements and application-specific datasets and less interoperability. Prior to the release of the Best Practices, there was greater ambiguity and disagreement in what constitutes correctly-formed GTFS data.
+
+### How were they developed? Who developed them?
+
+These Best Practices were developed by a working group of 17 organizations involved in GTFS, including app providers & data consumers, transit providers, and consultants with extensive involvement in GTFS. The working group was convened and facilitated by [Rocky Mountain Institute](http://www.rmi.org/mobility).
+
+Working Group members voted on each Best Practice. Most Best Practices were approved by a unanimous vote. In a minority of cases, Best Practices were approved a large majority of organizations.
+
+Some GTFS Best Practices have been merged into the spec and have been removed from this document.
+
+### Why not change the GTFS Reference directly?
+
+Good question!
+The process of examining the Specification, data usage and needs did indeed trigger some changes to the Specification.
+The Best Practices were created to bring everyone's understanding of the spec into harmony with the intention for some to be added into the spec and undergo the larger governance process, and others to be moved into a "how-to" guide.
+Since then, some Best Practices have been added into the spec based on their level of adoption and community consensus.
+To contribute to this effort, please go to the [GTFS Reference GitHub repository](https://github.com/google/transit/), or contact [specifications@mobilitydata.org](mailto:specifications@mobilitydata.org).
+
+### How to check for conformance with these Best Practices?
+
+The Canonical GTFS Schedule Validator checks for compliance against the GTFS Best Practices that can be automatically verified. Each [warning](https://gtfs-validator.mobilitydata.org/rules.html#WARNING-table) corresponds to recommendations that are either explicitly suggested by the GTFS Schedule Reference, using the term “recommend” or “should,” or mentioned in this document.
+You can find more about this validation tool on the [validate page](https://gtfs.org/schedule/validate/).
+
+### I represent a transit agency. What steps can I take so that our software service providers and vendors follow these Best Practices?
+
+Refer your vendor or software service provider to these Best Practices. We recommend referencing the GTFS Best Practices URL, as well as core Spec Reference in procurement for GTFS-producing software.
+
+### What should I do if I notice a GTFS data feed does not conform to the GTFS Best Practices?
+
+Identify the contact for the feed, using the `feed_contact_email` or `feed_contact_url` fields in [feed_info.txt](https://gtfs.org/schedule/reference/#feed_infotxt) if they are provided, or looking up contact information on the transit agency or feed producer website. When communicating the issue to the feed producer, link to the specific GTFS Best Practice that isn't being followed using this document (See ["Linking to this Document"](#linking-to-this-document)) or [the appropriate warning](https://gtfs-validator.mobilitydata.org/rules.html#WARNING-table) in the Canonical GTFS Schedule Validator if available.
+
+### How to propose new Best Practices?
+
+New Best Practices are now being added directly into the [spec](https://gtfs.org/schedule/reference/) in order to gradually consolidate both documents.
+If you'd like to suggest a new best practice, please go to the [GTFS Reference GitHub repository](https://github.com/google/transit/), [open an issue](https://github.com/google/transit/issues/new/choose) or create a Pull Request, or contact [specifications@mobilitydata.org](mailto:specifications@mobilitydata.org).
+
+## About This Document
+
+### Objectives
+
+The objectives of these GTFS Best Practices are:
+
+* Support greater interoperability of transit data
+* Improve end-user customer experience in public transportation apps
+* Make it easier for software developers to deploy and scale applications, products, and services
+* Facilitate the use of GTFS in various application categories (beyond its original focus on trip planning)
+
+### Linking to This Document
+
+Please link here in order to provide feed producers with guidance for correct formation of GTFS data. Each individual recommendation has an anchor link. Click the recommendation to get the URL for the in-page anchor link.
+
+If a GTFS-consuming application makes requirements or recommendations for GTFS data practices that are not described here, it is recommended to publish a document with those requirements or recommendations to supplement these common best practices.
+
+### GTFS Best Practices Working Group
+
+The GTFS Best Practices Working Group was convened by [Rocky Mountain Institute](http://rmi.org/) in 2016-17, consisting of public transportation providers, developers of GTFS-consuming applications, consultants, and academic organizations to define common practices and expectations for GTFS data.
+Members of this working group included:
+
+* [Cambridge Systematics](https://www.camsys.com/)
+* [Capital Metro](https://www.capmetro.org/)
+* [Center for Urban Transportation Research at University of South Florida](https://www.cutr.usf.edu/)
+* [Conveyal](http://conveyal.com/)
+* [Google](https://www.google.com/)
+* [IBI Group](http://www.ibigroup.com/)
+* [Mapzen](https://mapzen.com/)
+* [Microsoft](https://www.microsoft.com/)
+* [Moovel](https://www.moovel.com/)
+* [Oregon Department of Transportation](http://www.oregon.gov/odot/)
+* [Swiftly](https://goswift.ly/)
+* [Transit](https://transitapp.com/)
+* [Trillium](http://trilliumtransit.com/)
+* [TriMet](https://trimet.org/)
+* [World Bank](http://www.worldbank.org/)
+
+Today, this document is maintained by [MobilityData](http://mobilitydata.org/).
diff --git a/gtfs/best-practices/images/branching.svg b/gtfs/best-practices/images/branching.svg
new file mode 100644
index 00000000..5347f2b1
--- /dev/null
+++ b/gtfs/best-practices/images/branching.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gtfs/best-practices/images/inlining.svg b/gtfs/best-practices/images/inlining.svg
new file mode 100755
index 00000000..616575da
--- /dev/null
+++ b/gtfs/best-practices/images/inlining.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gtfs/best-practices/images/lasso-route.svg b/gtfs/best-practices/images/lasso-route.svg
new file mode 100755
index 00000000..7c32dff6
--- /dev/null
+++ b/gtfs/best-practices/images/lasso-route.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gtfs/best-practices/images/loop-route.svg b/gtfs/best-practices/images/loop-route.svg
new file mode 100755
index 00000000..def8b9e3
--- /dev/null
+++ b/gtfs/best-practices/images/loop-route.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gtfs/best-practices/images/rmi-small.png b/gtfs/best-practices/images/rmi-small.png
new file mode 100644
index 00000000..e2d65e39
Binary files /dev/null and b/gtfs/best-practices/images/rmi-small.png differ
diff --git a/gtfs/best-practices/images/rmi.png b/gtfs/best-practices/images/rmi.png
new file mode 100644
index 00000000..58bdcec4
Binary files /dev/null and b/gtfs/best-practices/images/rmi.png differ