November 4th, 2026 by Theo Döllmann
Large-Scale Train Delay Predictions
Travelling by train can be troublesome. Each journey is like gambling. Will you make it? The honest answer is not “yes” or “no”, but something like “probably, with a 60 % chance”. Answering a question like this is exactly what I have been working on for the past few years, and in this post I want to share how I plan to answer it not just for Germany, but for the whole world.
Some Background
Before I start, there are three projects that you need to know about for this post:
- Bahn-Vorhersage is a journey planner I developed for German railways. It predicts how likely it is that each of your transfers works out and ranks journeys by their reliability.
- Transitous is a community-run, free and open public transport routing service covering large parts of the world. It collects timetables (and, where available, realtime data) from hundreds of transit agencies.
- MOTIS is the open-source routing engine that powers Transitous. It is the thing that actually finds your journey from A to B.
The goal is to bring Bahn-Vorhersage-style reliability predictions to Transitous. Instead of just scaling up, I want to use this opportunity to rethink and improve the prediction methodology itself.
This post is a look into my research and planning process. It is organized into five topics:
- Existing Approaches
- Prediction Horizons
- Worldwide Generalization
- Cancellations and Extreme Delays
- Production Setup Considerations
A Quick Tour of What Exists
Before building something new, it is worth looking at what is already out there. There are huge number of research papers on train delay prediction, and a growing number of apps that show you how likely your transfer is to work out. I will not even try to give a complete picture. Instead, here is a hand-picked selection of projects and papers that are relevant to the problem I am trying to solve. If you want the full picture of the scientific part of the landscape, Spanninger et al. (2022) and Tiong et al. (2023) have both written literature reviews.
Let’s start with the projects you can actually use today:
- Wahrscheinlich-Ankommen, Zugfinder and chuuchuu show transfer reliabilities based on historical data. As far as I can tell (none of them are open source), they look up how often a given transfer has worked in the past.
- TeSpace (Durner 2024) is a probabilistic routing engine, mostly for Germany. Instead of the scheduled arrival, it optimizes for the expected arrival time, so it can find journeys that are not possible according to the timetable but likely work out in practice. It uses delay distributions aggregated per train category.
- Bahn-Vorhersage predicts a full delay distribution for every train at every transfer with XGBoost and computes transfer reliabilities from them. Tests have shown that these reliabilities are almost perfectly calibrated.
On the research side, I picked four papers that each tackle a part of my problem. Table 1 puts everything side by side.
| Project | Region | Method | Long | Short | FOSS |
|---|---|---|---|---|---|
| Wahrscheinlich-Ankommen | DE | Historical lookup | ✓ | ✗ | ✗ |
| Zugfinder | Many EU | Historical lookup | ✓ | ✗ | ✗ |
| chuuchuu | Many EU | Historical lookup | ✓ | ✗ | ✗ |
| TeSpace (Durner 2024) | DE | Aggregated distributions per train category | ✓ | ✓ | ✓ |
| Bahn-Vorhersage | DE | XGBoost | ✓ | ✓ | ✓ |
| Keyhani et al. | DE | Historical distributions | ✓ | ✓ | ✗ |
| Wang and Work | US | Autoregressive | ◐ | ◐ | ✗ |
| Nair et al. | DE | Ensemble (random forests, simulation, kernel regression) | ◐ | ◐ | ✗ |
| Spanninger et al. | CH | Neural network | ✗ | ✓ | ✗ |
No model-based approach covers more than one country, and only TeSpace and Bahn-Vorhersage handle both horizons with a single model. The only multi-region approaches are historical lookups, which will not work for Transitous, as we will see.
Question 1: Can One Model Do Long-Term and Short-Term?
Think about when you actually care whether a transfer works. Maybe you are booking a trip, weeks or even months in advance. Or you are about to leave the house and want to know which of the next few connections is the safest bet. Or you are already sitting on a delayed train and wonder whether you should replan your journey. These are all the same question, but from a prediction point of view they are very different.
Defining the Horizons
To talk about this properly, I use two terms:
- Long-term predictions are made when there is no information about the current state of the railway network. Nobody knows yet whether the train will be late, so all we can rely on is what usually happens.
- Short-term predictions are made when we do know something about the current state. Either we know the current delay of the train in question, or we know delays of other trains that our train might interact with.
These are my own definitions. Other authors draw the line differently or call the short-term case “online”. So when a paper claims to do long-term prediction, it is worth checking what exactly the authors mean.
How Others Handle It
Most approaches pick one of the two scenarios, or build a separate model for each.
Wang and Work (2015) built two autoregressive models for Amtrak trains in the US, one for each horizon. Compared to the timetable, they reduce the prediction error (RMSE) by 12 % and 60 % in the long-term and short-term settings, respectively. Those numbers give a feeling for how much more there is to gain once realtime data is available.
Nair et al. (2019) went much bigger. For Deutsche Bahn, they built an ensemble of 22 random forests with over 400 engineered features, together with a simulation-based model and a kernel regression model. With 50 million data points, it is the largest dataset I have found that wasused in the literature. They also use different models for trains that are already running or that are not. They predict up to 24 hours ahead. The results show a clear pattern: the further into the future, the smaller the improvement over the timetable baseline.
On the deployed side, TeSpace and Bahn-Vorhersage both use a single model for both horizons. TeSpace looks up delay distributions based on the train category, the currently predicted delay and how far into the future the prediction lies. Bahn-Vorhersage gives the current delay to XGBoost as a feature and is explicitly trained with and without it, so the same model can answer both kinds of questions.
How Far Ahead Can We See?
Why does the advantage shrink so quickly with longer horizons? Spanninger et al. (2024) offer a nice answer. They built an uncertainty-aware neural network for short-term predictions on Swiss railways and split its uncertainty into two parts: epistemic uncertainty, which comes from the model not knowing better, and aleatoric uncertainty, which comes from the randomness in the data itself. As the prediction horizon grows, the epistemic uncertainty stays almost constant, while the aleatoric uncertainty rises quickly.
In other words: the models are not getting worse; the future is just getting more random. Beyond a certain horizon, no model will be able to tell you the exact delay. This is why predicting a full probability distribution instead of a single number is so important. If we cannot know the delay, we can at least be honest about how uncertain it is.
My Answer
I want a single model that can do any-term predictions. It should give a sensible answer whether a train leaves in three months or has already left the previous station. To get there, I combine two ideas.
Predict the deviation, not the delay. Instead of predicting the total delay, the model predicts how much the actual delay will differ from the operator’s current prediction. In the long-term case there is no current prediction, so the model simply predicts the delay. In the short-term case, the model learns how far the operator’s prediction can be trusted. Like Bahn-Vorhersage today, the model is trained on both cases, so it learns to handle each of them.
Cut the chain when reality catches up. As I explain in the next section, I plan to predict delays segment by segment along the route of a train. Once a train has actually arrived at or departed from a stop, there is no need to predict anything up to that point. The actual time replaces the predicted distribution, and the predictions start from there.
Together, these ideas should give one model that gracefully moves from “this is what usually happens” to “this is what is happening right now” as departure gets closer.
Question 2: How Do You Predict Delays for the Whole World?
So far, everything I have built for Bahn-Vorhersage was designed for Germany. In Germany, I am able to collect all the data from a single data source. The gathering process is tedious, but it provides realtime data for all rail services in Germany, and more than 90 % of trains have stable train numbers. While I think this is embarrassingly poor-quality data for a country like Germany, it is still much better than in many other regions.
Why Historical Lookups Do Not Work
The simplest way to estimate whether a transfer works is to look it up: how often did train A arrive in time for train B in the past? This is what Wahrscheinlich-Ankommen, Zugfinder and chuuchuu do, and it works surprisingly well, as long as you can tell which train is which.
In Transitous, you often cannot. Timetables come in formats like GTFS or NeTEx, which do not necessarily provide stable IDs for trips. The Swiss feed, for example, has stable IDs; the German one does not. The identifier of a trip can change with every timetable update, and train numbers are not necessarily included at all. On top of that, lookups fail by design for anything new: a new line, a changed timetable or a rerouted service has no history, so there is nothing to look up until enough new data has been collected.
So instead of asking “how did this train perform?”, we need to ask “how do trains like this one perform?” This is exactly what a feature-based model like XGBoost does. It does not care about the identity of a trip, only about its properties: the kind of service, the stop, the time of day, the position along the route, how long the train has been running, and so on. A brand-new train that looks like an existing one gets similar predictions from day one.
Not Every Railway Is the Same
The second problem is that delay patterns differ a lot between countries, operators and regions. A Swiss intercity train, a British commuter train, an American long-distance train and a Chinese high-speed train have very little in common. A single model for the whole world needs to be able to learn the differences between them.
None of the approaches in Table 1 has attempted this, so this is where I expect most of the surprises. The good news is that tree-based models like XGBoost are quite good at learning separate rules for different groups in the data. Whether that is enough, or whether some regions need their own model, is something the data will have to show.
Missing Realtime Data
The third problem is realtime coverage. It is missing in many places, but there is no simple pattern to where it is missing. Where no historical realtime data is available, I want to be transparent and not make any delay predictions.
My plan is to make this part of the training process. The training data contains trips with and without realtime data. The model’s objective is to predict not only the delay but also whether realtime data is available. During inference, the delay prediction is only used when the likelihood of missing realtime data is low. This is basically like training an ML-based filter, except that it is all done by a single model.
Following the Path of a Train
The last idea in this section is the one I am most excited about. Bahn-Vorhersage currently predicts the delay at each stop independently. The prediction for the fifth stop of a train knows nothing about the prediction for the fourth stop. That is a bit odd, because a train that is late at the fourth stop will probably also be late at the fifth stop.
Instead of predicting the delay at each stop, I want to predict how much the run time between two stops and the dwell time at each stop differ from the timetable. The delay distribution at a stop is then the sum of all segment predictions before it, as shown in Figure 1.
The model becomes path-aware: delays build up along the route instead of appearing out of nowhere. It fits the short-term case perfectly, because the chain can be cut wherever real times are known (see Question 1). And it generalizes well, because a segment between two stops is a much more universal concept than a specific train at a specific stop. I have done some (so far unpublished) research on how much path awareness helps a prediction model, and the results make me optimistic. At least in Germany, there are some route sections that create a lot more delay than others.
I have already shown that long-term dwell-time predictions with XGBoost work for German railways (Döllmann 2026). I have a strong feeling that the same should work for run times. Keyhani et al. (2012) did something very similar: they combined run-time distributions per train and segment with minimum dwell times, minimum transfer times and the waiting rules for feeder trains from the German timetable. Their reliability ratings turned out to be very usable, though not perfectly calibrated, and they suspected that better input distributions would improve them. Better input distributions are exactly what a model like XGBoost should provide.
There is one simple safeguard I will add: trains do not leave early. Any probability of an early departure is moved to zero delay.
The biggest open question is how well the individual segment predictions combine. Summing distributions assumes the segments are independent, which they are certainly not. A train that is slow on one segment is probably still being driven by the same driver, in the same weather, on the same busy line on the next one. Small errors in every segment might add up to a large error at the end of a long route. How much this matters in practice is one of the first things I want to find out.
Question 3: What About Cancellations and Extreme Delays?
Many causes of delay are totally random (e.g. police activity, …). It is unlikely that we will ever be able to predict delays caused by random factors. Still, these events are part of the story, and very often they are the reason a transfer fails.
The Random Chaotic Problem
Some of the random factors follow patterns. More people get sick in winter, some train types fail more often, and weather is quite predictable a few days in advance. But the sheer number of semi-predictable factors makes delays hard to predict. When the buffer times in a schedule are tight, the situation becomes almost chaotic. A small delay on one train spreads to the next, and from there to the next. We will always find some patterns, but a chaotic system will never be very predictable.
This matches the research. Spanninger et al. (2024) showed that the uncertainty from randomness dominates as soon as we look a bit into the future. Nair et al. (2019) note that delays have a long-tailed distribution: most trains are on time or a little late, but there is a long tail of very large delays, and many of the factors behind them are random. In my experience, the very large delays in the long tail of the distribution are influenced by random factors more than smaller delays are. So I assume that large delays in general are less predictable than small ones.
Cancellations are Worse than Delays
From a passenger’s point of view, a cancelled train is the worst case. Your transfer does not just become tight; it disappears. Yet most of the literature focuses on delays and ignores cancellations entirely. Predicting both together seems to be a surprisingly under-researched topic.
My plan is to treat a cancellation as just another possible outcome. The training data contains cancelled trips, and the model predicts the probability of a cancellation alongside the probabilities of the different delays. The transfer reliability then naturally accounts for both delays and cancellations.
Coarser Buckets for Larger Delays
Bahn-Vorhersage currently predicts a discrete probability distribution with one class for every minute of delay between and minutes. That makes 34 classes, which is a lot, especially for XGBoost, where every additional class means more trees. At the same time, the range is not big enough. In Germany, this range only covers 97 % of all delays, and in other regions the coverage is probably even smaller.
But do we really need minute precision for large delays? If the model cannot know whether a train will be 23 or 27 minutes late because the delay was most likely caused by something random, there is no point in pretending otherwise. So instead of one class per minute, I want to use small buckets for small delays and larger buckets for larger ones. For example the positive cases:
The exact bucket boundaries in this example are made up. The real ones will come from the data by splitting the delays into buckets that contain roughly the same number of observations. That way, every class has enough training data, and the precision ends up where most of the delays are.
Question 4: How Expensive Is This, and Where Should It Run?
Good predictions are only useful if they arrive in time. Nobody wants to wait a minute for a journey planner to tell them whether their transfer works. And at the scale of Transitous, small costs add up quickly.
The Compute Budget
There are two ways to provide predictions: compute them ahead of time for every train and store them, or compute them on demand for the journeys a user actually asks for. Both have a cost.
Computing everything ahead of time means predicting a distribution for every stop of every trip in the world, and updating it whenever new realtime data comes in. The memory needed grows with the number of stop events multiplied by the number of classes.
Computing on demand avoids storing all of this, but moves the cost into the request. With the segment chain from Question 2, a prediction for one stop needs all segments before it, and a journey with several transfers needs predictions for several trains. The cost of a single XGBoost prediction grows with the number of trees, and for a classifier that number grows with the number of classes.
The more the service is used, the more worthwhile the first option becomes. However, when this is implemented as a new feature, demand is likely to be low, and on-demand predictions save a lot of compute.
Inside MOTIS or Next to It?
The most elegant solution would be to build the predictions directly into MOTIS. Then the routing itself could take reliability into account. Instead of rating the journeys MOTIS finds, it could search for reliable journeys and find alternatives that a timetable-only search would never suggest. Keyhani et al. (2012) showed that this is possible, although their integration is long gone from today’s MOTIS codebase.
Building the predictions into MOTIS would require computing them ahead of time as described above, because the routing touches many more trips than the journey ends up using. I would rather first find out what good predictions look like, and only then decide which shortcuts are acceptable.
So I will start with a separate service. MOTIS routes journeys as it does today, and the service applies the delay predictions and rates the reliability of each transfer. To keep things simple for apps built on top of Transitous, MOTIS can query the service itself and return the reliabilities together with the journeys, so no app has to implement any extra endpoint. Moving the predictions into the routing itself remains an option for later, once we know what they cost and what they are worth.
Where Things Stand
Right now, all of this is shifting from planning to implementation. The first piece is already running: I published the Transitous data archiver, which collects and stores the timetable and realtime feeds we will need for training. Next up is turning those raw feeds into something a model can actually learn from. I am currently building a parser on top of MOTIS to convert the archived GTFS data into a clean tabular format. Once that pipeline is in place, the real experiments can begin.
References
- Döllmann, Theo. 2026. “Predicting Train Dwell Times Using Xgboost and Simple Timetable Features for German Railways.” Other. https://opus.bibliothek.uni-augsburg.de/opus4/130259.
- Durner, Robin. 2024. “Stochastic Strategies for Public Transport Journeys Based on Realtime Delay Predictions.” Master's thesis, Universität Stuttgart. https://doi.org/10.18419/OPUS-14802.
- Keyhani, Mohammad H., Mathias Schnee, Karsten Weihe, and Hans-Peter Zorn. 2012. “Reliability and Delay Distributions of Train Connections.” 25 : 35–46. https://doi.org/10.4230/OASICS.ATMOS.2012.35.
- Nair, Rahul, Thanh Lam Hoang, Marco Laumanns, et al. 2019. “An Ensemble Prediction Model for Train Delays.” Transportation Research Part C: Emerging Technologies 104 (July): 196–209. https://doi.org/10.1016/j.trc.2019.04.026.
- Spanninger, Thomas, Alessio Trivella, Beda Büchel, and Francesco Corman. 2022. “A Review of Train Delay Prediction Approaches.” Journal of Rail Transport Planning & Management 22 (June): 100312. https://doi.org/10.1016/j.jrtpm.2022.100312.
- Spanninger, Thomas, Nina Wiedemann, and Francesco Corman. 2024. “Quantifying the Dynamic Predictability of Train Delay with Uncertainty-Aware Neural Networks.” Transportation Research Part C: Emerging Technologies 162 (May): 104563. https://doi.org/10.1016/j.trc.2024.104563.
- Tiong, Kah Yong, Zhenliang Ma, and Carl-William Palmqvist. 2023. “A Review of Data-Driven Approaches to Predict Train Delays.” Transportation Research Part C: Emerging Technologies 148 (March): 104027. https://doi.org/10.1016/j.trc.2023.104027.
- Wang, Ren, and Daniel B. Work. 2015. “Data Driven Approaches for Passenger Train Delay Estimation.” In “2015 IEEE 18th International Conference on Intelligent Transportation Systems.” Special issue, 2015 IEEE 18th International Conference on Intelligent Transportation Systems, September, 535–40. https://doi.org/10.1109/itsc.2015.94.