This leaves conservative (as in: careful, not willing to implement extensive heuristic workarounds) consumers with no other choice than marking the Schedule stop as cancelled/skipped and the other data source's stop as additional, causing bad routing results.
As of 2026-09-01T11:24:38+02:00, the latest VDV-454 AUS Komplettfahrt=true IstFahrt for the trip. Note that the rudimentary HaltID/stop_id matching works here, so there is a Schedule stop *:*:900340004*.
(using this DuckDB script)
SELECT DISTINCT ON (FahrtBezeichner, HaltID) t.*, stop_name FROM (SELECT * EXCLUDE ("$BestaetigungZst", Betriebstag, FahrtStartEnde, UmlaufID, FahrzeugTypID, RichtungsID, PrognoseMoeglich, Komplettfahrt, ServiceAttributs, AbfahrtssteigText, Einsteigeverbot, AnkunftssteigText, Aussteigeverbot, Durchfahrt, HinweisText), RichtungsID AS RiID, PrognoseMoeglich AS ProgMoegl FROM aus_isthalts WHERE Komplettfahrt = 'true' AND FahrtBezeichner = '3357-800158-8012943-200400#DB#DB' ORDER BY "$BestaetigungZst" DESC, Abfahrtszeit) t LEFT JOIN gtfs.stops ON t.HaltID = split_part(stops.stop_id, ':', 3) ORDER BY coalesce(Ankunftszeit, Abfahrtszeit);
┌──────────────────────────────────┬──────────────────────────┬──────────┬────────────┬───────────────┬───────────┬───────────┬──────────────────────────┬──────────────────────────┬──────────────────────────┬──────────────────────────┬────────────┬────────────────────────┬───────────┬─────────────────────────────────────────┐
│ FahrtBezeichner │ Zst │ LinienID │ LinienText │ RichtungsText │ FaelltAus │ HaltID │ Abfahrtszeit │ IstAbfahrtPrognose │ Ankunftszeit │ IstAnkunftPrognose │ Zusatzhalt │ RiID │ ProgMoegl │ stop_name │
│ varchar │ timestamp with time zone │ varchar │ varchar │ varchar │ boolean │ varchar │ timestamp with time zone │ timestamp with time zone │ timestamp with time zone │ timestamp with time zone │ boolean │ varchar │ boolean │ varchar │
├──────────────────────────────────┼──────────────────────────┼──────────┼────────────┼───────────────┼───────────┼───────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┼────────────┼────────────────────────┼───────────┼─────────────────────────────────────────┤
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900341110 │ 2026-08-31 20:04:00+02 │ NULL │ NULL │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Schwedt, Bahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900341111 │ 2026-08-31 20:06:00+02 │ NULL │ 2026-08-31 20:06:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Schwedt, Mitte Bhf │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900340003 │ 2026-08-31 20:18:00+02 │ NULL │ 2026-08-31 20:17:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Pinnow (UM), Bahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900340004 │ 2026-08-31 20:32:00+02 │ NULL │ 2026-08-31 20:26:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Angermünde, Bahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900350125 │ 2026-08-31 20:43:00+02 │ NULL │ 2026-08-31 20:42:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Chorin, Bahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900350124 │ 2026-08-31 20:47:00+02 │ NULL │ 2026-08-31 20:46:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Britz, Bahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900350127 │ 2026-08-31 20:53:00+02 │ NULL │ 2026-08-31 20:51:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Eberswalde, Hauptbahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900350160 │ 2026-08-31 21:08:00+02 │ NULL │ 2026-08-31 21:07:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ S Bernau Bhf │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900007102 │ 2026-08-31 21:24:00+02 │ NULL │ 2026-08-31 21:21:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ S+U Gesundbrunnen Bhf (Berlin) │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900003200 │ 2026-08-31 21:32:00+02 │ NULL │ 2026-08-31 21:29:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ S+U Berlin Hauptbahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900100020 │ 2026-08-31 21:35:00+02 │ NULL │ 2026-08-31 21:34:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ S+U Potsdamer Platz Bhf (Berlin) │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900058101 │ 2026-08-31 21:43:00+02 │ NULL │ 2026-08-31 21:39:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ S Südkreuz Bhf (Berlin) │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900064301 │ 2026-08-31 21:48:00+02 │ NULL │ 2026-08-31 21:47:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ S Lichterfelde Ost Bhf (Berlin) │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900220001 │ 2026-08-31 21:53:00+02 │ NULL │ 2026-08-31 21:52:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Teltow, Bahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900245032 │ 2026-08-31 21:57:00+02 │ NULL │ 2026-08-31 21:56:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Großbeeren, Bahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900245030 │ 2026-08-31 22:02:00+02 │ NULL │ 2026-08-31 22:01:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Ludwigsfelde, Birkengrund Bhf │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900245029 │ 2026-08-31 22:06:00+02 │ NULL │ 2026-08-31 22:05:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Ludwigsfelde, Bahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900245014 │ 2026-08-31 22:17:00+02 │ NULL │ 2026-08-31 22:17:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Woltersdorf (Nuthe-Urstromtal), Bahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900245016 │ 2026-08-31 22:22:00+02 │ NULL │ 2026-08-31 22:21:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Luckenwalde, Bahnhof │
│ 3357-800158-8012943-200400#DB#DB │ NULL │ 3357 │ RE3 │ NULL │ NULL │ 900245002 │ NULL │ NULL │ 2026-08-31 22:30:00+02 │ NULL │ NULL │ Schwedt(Oder)#Jüterbog │ true │ Jüterbog, Bahnhof │
└──────────────────────────────────┴──────────────────────────┴──────────┴────────────┴───────────────┴───────────┴───────────┴──────────────────────────┴──────────────────────────┴──────────────────────────┴──────────────────────────┴────────────┴────────────────────────┴───────────┴─────────────────────────────────────────┘
However, looking at the Schedule trip 304272689, we can see that it uses a different (non-IFOPT) stop_id for Angermünde Bahnhof.
SELECT stop_sequence_consec AS stop_seq_c, stop_id, stop_name, station_id, station_name, t_arrival, t_departure FROM arrivals_departures WHERE date = '2026-09-01' AND trip_id = '304272689' ORDER BY stop_sequence_consec;
┌────────────┬─────────────────────────┬──────────────────────────────────┬────────────────────┬──────────────────────────────────┬──────────────────────────┬──────────────────────────┐
│ stop_seq_c │ stop_id │ stop_name │ station_id │ station_name │ t_arrival │ t_departure │
│ int32 │ varchar │ varchar │ varchar │ varchar │ timestamp with time zone │ timestamp with time zone │
├────────────┼─────────────────────────┼──────────────────────────────────┼────────────────────┼──────────────────────────────────┼──────────────────────────┼──────────────────────────┤
│ 0 │ de:12073:900341110:1:50 │ Schwedt, Bahnhof │ de:12073:900341110 │ Schwedt, Bahnhof │ 2026-09-01 20:04:00+02 │ 2026-09-01 20:04:00+02 │
│ 1 │ de:12073:900341111:1:50 │ Schwedt, Mitte Bhf │ de:12073:900341111 │ Schwedt, Mitte Bhf │ 2026-09-01 20:06:00+02 │ 2026-09-01 20:06:00+02 │
│ 2 │ de:12073:900340003:1:50 │ Pinnow (UM), Bahnhof │ de:12073:900340003 │ Pinnow (UM), Bahnhof │ 2026-09-01 20:17:00+02 │ 2026-09-01 20:18:00+02 │
│ 3 │ 000300570037 │ Angermünde, Bahnhof │ de:12073:900340004 │ Angermünde, Bahnhof │ 2026-09-01 20:26:00+02 │ 2026-09-01 20:32:00+02 │
│ 4 │ de:12060:900350125:2:51 │ Chorin, Bahnhof │ de:12060:900350125 │ Chorin, Bahnhof │ 2026-09-01 20:42:00+02 │ 2026-09-01 20:43:00+02 │
│ 5 │ de:12060:900350124:2:51 │ Britz, Bahnhof │ de:12060:900350124 │ Britz, Bahnhof │ 2026-09-01 20:46:00+02 │ 2026-09-01 20:47:00+02 │
│ 6 │ de:12060:900350127:3:53 │ Eberswalde, Hauptbahnhof │ de:12060:900350127 │ Eberswalde, Hauptbahnhof │ 2026-09-01 20:51:00+02 │ 2026-09-01 20:53:00+02 │
│ 7 │ de:12060:900350160:2:52 │ S Bernau Bhf │ de:12060:900350160 │ S Bernau Bhf │ 2026-09-01 21:07:00+02 │ 2026-09-01 21:08:00+02 │
│ 8 │ de:11000:900007102:4:57 │ S+U Gesundbrunnen Bhf (Berlin) │ de:11000:900007102 │ S+U Gesundbrunnen Bhf (Berlin) │ 2026-09-01 21:21:00+02 │ 2026-09-01 21:24:00+02 │
│ 9 │ de:11000:900003200:1:50 │ S+U Berlin Hauptbahnhof │ de:11000:900003201 │ S+U Berlin Hauptbahnhof │ 2026-09-01 21:29:00+02 │ 2026-09-01 21:32:00+02 │
│ 10 │ de:11000:900100020:1:50 │ S+U Potsdamer Platz Bhf (Berlin) │ de:11000:900100020 │ S+U Potsdamer Platz Bhf (Berlin) │ 2026-09-01 21:34:00+02 │ 2026-09-01 21:35:00+02 │
│ 11 │ de:11000:900058101:2:53 │ S Südkreuz Bhf (Berlin) │ de:11000:900058101 │ S Südkreuz Bhf (Berlin) │ 2026-09-01 21:39:00+02 │ 2026-09-01 21:43:00+02 │
│ 12 │ de:11000:900064301:1:50 │ S Lichterfelde Ost Bhf (Berlin) │ de:11000:900064301 │ S Lichterfelde Ost Bhf (Berlin) │ 2026-09-01 21:47:00+02 │ 2026-09-01 21:48:00+02 │
│ 13 │ de:12069:900220001:1:50 │ Teltow, Bahnhof │ de:12069:900220001 │ Teltow, Bahnhof │ 2026-09-01 21:52:00+02 │ 2026-09-01 21:53:00+02 │
│ 14 │ de:12072:900245032:1:50 │ Großbeeren, Bahnhof │ de:12072:900245032 │ Großbeeren, Bahnhof │ 2026-09-01 21:56:00+02 │ 2026-09-01 21:57:00+02 │
│ 15 │ de:12072:900245030:1:50 │ Ludwigsfelde, Birkengrund Bhf │ de:12072:900245030 │ Ludwigsfelde, Birkengrund Bhf │ 2026-09-01 22:01:00+02 │ 2026-09-01 22:02:00+02 │
│ 16 │ de:12072:900245029:1:51 │ Ludwigsfelde, Bahnhof │ de:12072:900245029 │ Ludwigsfelde, Bahnhof │ 2026-09-01 22:05:00+02 │ 2026-09-01 22:05:00+02 │
└────────────┴─────────────────────────┴──────────────────────────────────┴────────────────────┴──────────────────────────────────┴──────────────────────────┴──────────────────────────┘
SELECT stop_id, stop_name, parent_station AS station_id FROM stops WHERE stop_id = '000300570037';
┌──────────────┬─────────────────────┬────────────────────┐
│ stop_id │ stop_name │ station_id │
│ varchar │ varchar │ varchar │
├──────────────┼─────────────────────┼────────────────────┤
│ 000300570037 │ Angermünde, Bahnhof │ de:12073:900340004 │
└──────────────┴─────────────────────┴────────────────────┘
Describe the enhancement/addition to the feed you'd like to suggest
Currently, the VBB GTFS Schedule feed contains many trips with
stop_timesentries that reference non-IFOPT-style (non-DHID-style) stop IDs.While this is technically correct, and while it usually doesn't prevent matching the trip with external data sources, it causes stops not to be matched, aside from implementing heuristic stop matching and risking false positives.
This leaves conservative (as in: careful, not willing to implement extensive heuristic workarounds) consumers with no other choice than marking the Schedule stop as cancelled/skipped and the other data source's stop as additional, causing bad routing results.
An example from VBB's own GTFS-RT feed:
Last update of GTFS Feed
2026-08-27