Skip to main content
Every event in GDELT Cloud carries two different dates, and confusing them is the single easiest way to build a backtest that looks brilliant and is wrong. event_date is a claim about the world. coded_at is a claim about us. A backtest that filters on event_date alone is asking “what happened by date D”, which is a question no one could have answered on date D.

The as-of claim we do make

Filtering on when an event was coded gives you the set of events that existed in GDELT Cloud at that time. That is a real point-in-time view, and it is auditable in both directions:
  • The coding timestamp is populated on 100% of events, stamped once when the coder emits the event and never revised.
  • Every event carries source_urls — the actual articles it was derived from. Nothing is coded from a source we do not cite, so you can go read the evidence that was available at the time.
What we do not claim. This is not a full bitemporal history. We record when an event first appeared; we do not publish a revision log of every subsequent correction to that event’s fields. If an event’s actors or geography were later refined, the record carries the refined version with the original coding timestamp. Treat it as “first known at”, not “unchanged since”.And there is no vintaged replay of past values — not in the bulk files, not on the API, and not at any plan tier. as_of is refused on /api/v2/events for exactly this reason. Bounding by when we coded something is the whole of what we offer here.

How to ask for it

The lever has a different name on each surface, and there is no as_of on events.
as_of on /api/v2/events returns 400, deliberately. Event metrics are computed live and are not vintaged, so as_of could not return a reproducible point-in-time result there — and answering 200 with a plausible-looking result would be worse than refusing. Use observed_start / observed_end, which bound something we actually record. as_of is supported where the data is genuinely vintaged: /macro/observations, /screening/match and the Atlas /intelligence/* surfaces.

Why events are coded after the day they happened

Measured over the seven days ending 2026-07-21, across 11,993 events: the median gap between an article becoming available to us and its coded event being queryable is 38 minutes, with a 90th percentile of 61 minutes. 89.1% of events are available within the hour. Lag measured the other way — against event_date rather than against the article — looks much larger, and the difference is mostly arithmetic rather than processing. Three real causes, in order.

1. Hourly cadence

Ingest runs on the top of every hour, so there is an irreducible sub-hour quantisation: an article that appears just after a run waits for the next one. The floor is set by the cycle, not by processing time, which is why the median lands near half a cycle plus the pipeline’s own duration. A separate catch-up pass runs near the end of each hour and sweeps clusters the main run did not reach, and range backfills re-code historical windows when coverage gaps are found.

2. Publication lag in the sources themselves

event_date is when the event occurred, not when it was reported. Local and non-English outlets frequently publish on D+1 about a D event, and for some regions that is the only coverage. The conflict family shows this most.

3. The midnight boundary — an artefact, not a delay

event_date is a date, not a timestamp. An event that happened at 22:00 UTC and was coded at 23:00 UTC — one hour later — already registers as “coded the same day” with almost no margin, and one coded at 00:30 registers as a next-day event on a 90-minute pipeline. Most of the apparent day-scale lag against event_date is this, not work in progress.
We do not wait for corroboration before coding. A story does not have to accumulate articles to become codeable — single-article clusters are a first-class coding path and are the majority of what we code. Measured over the same window, computing latency from the earliest contributing article, including everything that arrived later, moves the median by 32 seconds (2,332 s vs 2,300 s). If coverage had to accrete before an event could be coded, that gap would be hours.

Later-coded events are better evidenced — but that is selection, not waiting

Comparing events coded within a day of their event_date against those coded in the following day: The reason is which net caught them, not how long they sat. The hourly catch-up pass targets clusters the main run left uncoded and requires at least two articles, so the events it recovers are by construction the better-corroborated ones. Either way the practical conclusion holds: if you drop the tail to get a tighter latency number, you are dropping your best-evidenced events.

How to use this in a backtest

1

Filter on when we coded it, not on when it happened

For a signal you claim to have had at time T, bound observed_end at T. Filtering on event_date alone silently imports hindsight.
2

Set your decision lag from the distribution, not the median

If your strategy acts on same-day information, model a decision point at T+24h and accept that you will see roughly 89% of the day’s events. If it can wait, T+48h gets you effectively all of them, with better evidence.
3

Do not treat a thin day as a quiet day

A day with an unusually low event count near the present is more likely still filling in than genuinely calm. Re-pull recent windows before drawing a conclusion about them, and prefer windows that are at least 48 hours old.
4

Check the file's own as-of stamp

Every bulk file carries an as_of value that reports what the weakest partition in it knew — the minimum across dates, not the maximum, so one freshly settled day cannot vouch for a stale month.

Where these numbers come from

The latency figures are measured against the production events table over the stated windows, not modelled, and the same measurement is published on the methodology page. They will drift as the pipeline changes; the shape of the distribution — an hourly mode plus a catch-up mode — is the stable part, and the exact percentiles are not a contractual guarantee.