SSignal / ChicagoCTA reliability, explained simplyConnecting to live data

BUILT FROM A RIDER'S FRUSTRATION / DEVELOPMENT SNAPSHOT

Can I trust this
arrival time?

CTA and Ventra tell us when a train is expected. Signal Chicago checks whether that estimate stays steady and whether trains are coming as evenly as the schedule says they should.

I built this after repeatedly planning around an ETA that changed while I was waiting. The goal is to help another rider understand the situation before making the same decision.

114 arrival estimates saved0 checks in the last 24h12 stations monitored0 lines with larger gaps now

THE 30-SECOND EXPLANATION

We do not replace the CTA estimate.
We test how dependable it looks.

1CTA posts an ETA

For example: “Your train should arrive in 8 minutes.”

2We save it

Two minutes later, we save the next estimate for the same train.

3We compare it

If 8 minutes becomes 11, then 13, the promise has not been steady.

4We explain it

The rider sees a simple status. The arrow reveals the analyst evidence.

HOW THE CTA LOOKS RIGHT NOW

Start with the plain-English answer.

These are current predictions, not permanent grades. Open the arrow on any line to see the exact measurements and formulas behind the simple status.

Close to scheduleLarger gapsMuch larger gapsLimited data
Red LineLimited gap data10.5 minaverage predicted waitThere are current arrivals, but not enough consecutive trains to compare their spacing. We are still building the ETA-change history.
ANALYST VIEW

Evidence behind the rider status

Current average wait10.5 min

Average time from the latest CTA snapshot to the upcoming predicted arrivals.

ETA movementBuilding history

Average absolute change in the same train's promised arrival time.

Predicted train gapNot enough data

Spacing between consecutive predicted trains in the same direction.

Scheduled spacingNot enough data

Typical spacing calculated from CTA's GTFS schedule for this time period.

Gap vs. scheduleNot enough data

Predicted gap divided by scheduled spacing. 1.0x is close to plan; 2.0x is about double.

Snapshot coverage15 arrivals / 3 stations

This is the monitored sample behind the current route reading.

Formula: Gap vs. schedule = predicted train gap ÷ scheduled spacing. These labels are Signal Chicago display rules, not official CTA categories.

Blue LineLimited gap data1.7 minaverage predicted waitThere are current arrivals, but not enough consecutive trains to compare their spacing. We are still building the ETA-change history.
ANALYST VIEW

Evidence behind the rider status

Current average wait1.7 min

Average time from the latest CTA snapshot to the upcoming predicted arrivals.

ETA movementBuilding history

Average absolute change in the same train's promised arrival time.

Predicted train gapNot enough data

Spacing between consecutive predicted trains in the same direction.

Scheduled spacingNot enough data

Typical spacing calculated from CTA's GTFS schedule for this time period.

Gap vs. scheduleNot enough data

Predicted gap divided by scheduled spacing. 1.0x is close to plan; 2.0x is about double.

Snapshot coverage1 arrivals / 1 stations

This is the monitored sample behind the current route reading.

Formula: Gap vs. schedule = predicted train gap ÷ scheduled spacing. These labels are Signal Chicago display rules, not official CTA categories.

Brown LineLimited gap data0.7 minaverage predicted waitThere are current arrivals, but not enough consecutive trains to compare their spacing. We are still building the ETA-change history.
ANALYST VIEW

Evidence behind the rider status

Current average wait0.7 min

Average time from the latest CTA snapshot to the upcoming predicted arrivals.

ETA movementBuilding history

Average absolute change in the same train's promised arrival time.

Predicted train gapNot enough data

Spacing between consecutive predicted trains in the same direction.

Scheduled spacingNot enough data

Typical spacing calculated from CTA's GTFS schedule for this time period.

Gap vs. scheduleNot enough data

Predicted gap divided by scheduled spacing. 1.0x is close to plan; 2.0x is about double.

Snapshot coverage1 arrivals / 1 stations

This is the monitored sample behind the current route reading.

Formula: Gap vs. schedule = predicted train gap ÷ scheduled spacing. These labels are Signal Chicago display rules, not official CTA categories.

Green LineLimited gap data12.8 minaverage predicted waitThere are current arrivals, but not enough consecutive trains to compare their spacing. We are still building the ETA-change history.
ANALYST VIEW

Evidence behind the rider status

Current average wait12.8 min

Average time from the latest CTA snapshot to the upcoming predicted arrivals.

ETA movementBuilding history

Average absolute change in the same train's promised arrival time.

Predicted train gapNot enough data

Spacing between consecutive predicted trains in the same direction.

Scheduled spacingNot enough data

Typical spacing calculated from CTA's GTFS schedule for this time period.

Gap vs. scheduleNot enough data

Predicted gap divided by scheduled spacing. 1.0x is close to plan; 2.0x is about double.

Snapshot coverage22 arrivals / 5 stations

This is the monitored sample behind the current route reading.

Formula: Gap vs. schedule = predicted train gap ÷ scheduled spacing. These labels are Signal Chicago display rules, not official CTA categories.

Orange LineLimited gap data16.0 minaverage predicted waitThere are current arrivals, but not enough consecutive trains to compare their spacing. We are still building the ETA-change history.
ANALYST VIEW

Evidence behind the rider status

Current average wait16.0 min

Average time from the latest CTA snapshot to the upcoming predicted arrivals.

ETA movementBuilding history

Average absolute change in the same train's promised arrival time.

Predicted train gapNot enough data

Spacing between consecutive predicted trains in the same direction.

Scheduled spacingNot enough data

Typical spacing calculated from CTA's GTFS schedule for this time period.

Gap vs. scheduleNot enough data

Predicted gap divided by scheduled spacing. 1.0x is close to plan; 2.0x is about double.

Snapshot coverage6 arrivals / 2 stations

This is the monitored sample behind the current route reading.

Formula: Gap vs. schedule = predicted train gap ÷ scheduled spacing. These labels are Signal Chicago display rules, not official CTA categories.

Purple LineNo current arrivals0.0 minaverage predicted waitCTA is not currently returning enough arrivals for this monitored sample.
ANALYST VIEW

Evidence behind the rider status

Current average wait0.0 min

Average time from the latest CTA snapshot to the upcoming predicted arrivals.

ETA movementBuilding history

Average absolute change in the same train's promised arrival time.

Predicted train gapNot enough data

Spacing between consecutive predicted trains in the same direction.

Scheduled spacingNot enough data

Typical spacing calculated from CTA's GTFS schedule for this time period.

Gap vs. scheduleNot enough data

Predicted gap divided by scheduled spacing. 1.0x is close to plan; 2.0x is about double.

Snapshot coverage0 arrivals / 0 stations

This is the monitored sample behind the current route reading.

Formula: Gap vs. schedule = predicted train gap ÷ scheduled spacing. These labels are Signal Chicago display rules, not official CTA categories.

Pink LineLimited gap data14.9 minaverage predicted waitThere are current arrivals, but not enough consecutive trains to compare their spacing. We are still building the ETA-change history.
ANALYST VIEW

Evidence behind the rider status

Current average wait14.9 min

Average time from the latest CTA snapshot to the upcoming predicted arrivals.

ETA movementBuilding history

Average absolute change in the same train's promised arrival time.

Predicted train gapNot enough data

Spacing between consecutive predicted trains in the same direction.

Scheduled spacingNot enough data

Typical spacing calculated from CTA's GTFS schedule for this time period.

Gap vs. scheduleNot enough data

Predicted gap divided by scheduled spacing. 1.0x is close to plan; 2.0x is about double.

Snapshot coverage10 arrivals / 2 stations

This is the monitored sample behind the current route reading.

Formula: Gap vs. schedule = predicted train gap ÷ scheduled spacing. These labels are Signal Chicago display rules, not official CTA categories.

Yellow LineNo current arrivals0.0 minaverage predicted waitCTA is not currently returning enough arrivals for this monitored sample.
ANALYST VIEW

Evidence behind the rider status

Current average wait0.0 min

Average time from the latest CTA snapshot to the upcoming predicted arrivals.

ETA movementBuilding history

Average absolute change in the same train's promised arrival time.

Predicted train gapNot enough data

Spacing between consecutive predicted trains in the same direction.

Scheduled spacingNot enough data

Typical spacing calculated from CTA's GTFS schedule for this time period.

Gap vs. scheduleNot enough data

Predicted gap divided by scheduled spacing. 1.0x is close to plan; 2.0x is about double.

Snapshot coverage0 arrivals / 0 stations

This is the monitored sample behind the current route reading.

Formula: Gap vs. schedule = predicted train gap ÷ scheduled spacing. These labels are Signal Chicago display rules, not official CTA categories.

RIDER QUESTION 01Can I trust the ETA?

We call the analyst measurement ETA movement. Smaller changes mean the promised time has been steadier.

RIDER QUESTION 02Are trains coming evenly?

Gap vs. schedule compares the predicted spacing between trains with what CTA planned for this time of day.

RIDER QUESTION 03Is this station reliable?

A live wait is only one moment. We need repeated days before giving a fair historical station reliability grade.

MONITORED STATIONS / LIVE SNAPSHOT

Check the wait without mistaking it for a grade.

The cards are sorted by current predicted wait. Open an arrow for the raw snapshot details.

01Green Line

35th-Bronzeville-IIT

12.4min
predicted wait

Moderate wait in this snapshot

SNAPSHOT DETAILS

5 upcoming arrivals currently visible.

0% are explicitly marked delayed by CTA.

Station reliability history: still collecting a fair multi-day baseline.

Important: a long wait right now does not automatically make this an unreliable station.
02Orange Line

35th/Archer

18.9min
predicted wait

Longer wait in this snapshot

SNAPSHOT DETAILS

5 upcoming arrivals currently visible.

0% are explicitly marked delayed by CTA.

Station reliability history: still collecting a fair multi-day baseline.

Important: a long wait right now does not automatically make this an unreliable station.
03Pink Line

54th/Cermak

18.4min
predicted wait

Longer wait in this snapshot

SNAPSHOT DETAILS

5 upcoming arrivals currently visible.

0% are explicitly marked delayed by CTA.

Station reliability history: still collecting a fair multi-day baseline.

Important: a long wait right now does not automatically make this an unreliable station.
04Red Line

95th/Dan Ryan

12.7min
predicted wait

Moderate wait in this snapshot

SNAPSHOT DETAILS

5 upcoming arrivals currently visible.

0% are explicitly marked delayed by CTA.

Station reliability history: still collecting a fair multi-day baseline.

Important: a long wait right now does not automatically make this an unreliable station.
05Blue Line

O'Hare

1.7min
predicted wait

Shorter wait in this snapshot

SNAPSHOT DETAILS

1 upcoming arrivals currently visible.

0% are explicitly marked delayed by CTA.

Station reliability history: still collecting a fair multi-day baseline.

Important: a long wait right now does not automatically make this an unreliable station.
06Brown Line

Kimball

0.7min
predicted wait

Shorter wait in this snapshot

SNAPSHOT DETAILS

1 upcoming arrivals currently visible.

0% are explicitly marked delayed by CTA.

Station reliability history: still collecting a fair multi-day baseline.

Important: a long wait right now does not automatically make this an unreliable station.

WHY I BUILT SIGNAL CHICAGO

The ETA helped me plan - until it kept changing while I waited.

I wanted a way to look beyond one arrival number. Signal Chicago keeps the earlier estimates, checks how they change, and asks whether the gap between trains matches the schedule.

WHAT HAPPENS EVERY TWO MINUTES

01Ask CTA

A protected cloud function requests new arrival estimates for twelve stations.

02Save the promise

The database keeps each estimate so it does not disappear when CTA updates it.

03Check the change

Repeated ETAs become stability measurements; train gaps are compared with the schedule.

04Explain it

The site shows the rider answer first and keeps the analyst evidence one arrow away.

Open the technical architecture

Source: CTA Train Tracker API and CTA GTFS schedule files.

Collector: Supabase Edge Function triggered by Supabase Cron every two minutes.

Storage: PostgreSQL with validation, collection audit records, 14-day raw retention, and daily summaries.

Website: Static Next.js dashboard on Cloudflare Pages, requesting a read-only summary every minute.

Rider labels: Below 1.3x is close to schedule; 1.3x-1.74x is a larger gap; 1.75x or more is a much larger gap. A 15+ minute average wait can also trigger a watch label. These are Signal Chicago rules, not CTA standards.

READ THIS PROJECT HONESTLY

Current prediction behavior

How long the predicted wait looks, whether ETAs have been steady, and whether train gaps look larger than scheduled.

Official on-time performance

The observatory studies CTA predictions for a 12-station sample. It does not yet track every completed arrival across the full network.

Fair station reliability

As more days are collected, Signal Chicago can compare stations by time of day without judging them from one bad moment.