DEV Community

Cover image for I parsed 110,000 EU procurement awards. Half of them don't say when the contract was signed.
Pennyforge
Pennyforge

Posted on

I parsed 110,000 EU procurement awards. Half of them don't say when the contract was signed.

Every two months or so, the EU publishes an open archive of everything its public authorities bought — Tenders Electronic Daily (TED), the official journal of the day for EU procurement. In October 2026 I downloaded the complete monthly packages for July, August and September 2026 — 1.16 GB of eForms/UBL XML, 213,716 notices, of which 110,217 are award notices (the documents that say who won what). I wrote four small Python scripts, parsed everything in about ten minutes, and got numbers the official statistics don't show you.

The rule: under Directive 2014/24/EU, Article 50(1), a contracting authority has 30 days to publish the award notice after the award is made. So a simple question: how often does that actually happen?

44% of award notices state no award date at all

Of the 110,217 award notices, 48,931 (44.4%) carry no usable award date. Not "late" — the field is filled with a sentinel value (the date 2000-01-01 and friends, the eForms schema's explicit "not stated" marker). What's interesting: in the September sample I checked the raw date values per notice — the sentinel appears in 73.7% of award notices as one of their dates, but only 44.1% of notices lack any usable date. The element is never absent; the authority actively says "not stated". Official TED statistics don't report this, so it's a data-quality finding in its own right: if you want to build a compliance or analytics pipeline on TED award data, nearly half of it won't have the field you want.

The three-month trend is boring (which is the good part)

For the notices that do state an award date, the picture is stable across all three months — this isn't a September artifact:

Month Award notices No usable award date Within 30 days Later than 90 days
Jul 2026 42,742 43.2% 45.9% 27.1%
Aug 2026 32,317 45.0% 46.3% 22.2%
Sep 2026 35,158 44.1% 47.2% 24.0%

So: roughly half of dated award notices respect the 30-day window, and roughly a quarter publish later than three months. If you'd bet on "95% comply", you'd lose in every month.

The honest twist: the long tail isn't what you'd think

The first version of this analysis reported a blunt "24% are 90+ days late". Then I stratified by notice type (eForms notice-type-code, the official codelist) and the story changed:

  • can-standard — standard competitive contract/concession awards, 82% of the population: 66.7% publish within 30 days, only 11.8% later than 90 days.
  • can-modif — contract modification notices: 71.4% later than 90 days. That's expected — a modification gets published long after the original award.
  • veat (voluntary ex-ante transparency) and can-social (light regime, below-threshold) sit in between.

The blended headline hides the decomposition. The core competitive market is faster than the average suggests; framework and modification filings drive the long tail. Any honest "EU procurement compliance" number has to say which population it covers.

The single-bidder map (and where I got it wrong)

A second question: when lots report how many tenders they received (ReceivedSubmissionsStatistics, code tenders), how often is the answer exactly one? Stable across the three months: about 32% of reporting lots are single-bid.

By buyer country (September, buyer = the contracting authority, cross-checked against the contract's place of performance — both agree within half a point for every country):

Top single-bid share Bottom
Greece 63.1% Finland 9.0%
Poland 53.7% Switzerland 10.2%
Slovenia 45.7% France 16.8%
Cyprus 44.4% Germany 19.9%
Czechia 41.5% Belgium 18.3%

Central and Eastern EU buyers award single-bid 2–3× as often as Western ones. I won't pretend that's pure competition — below-threshold and voluntary routes (where one tenderer is normal) and single-supplier frameworks both inflate the number, and I haven't fully stratified that cut yet. But the gradient is robust, and nobody seems to publish it.

Here's the cautionary tale for anyone working with TED: my first pass reported Luxembourg at 51.6% single-bid — the highest in the EU. It was wrong. The country field I'd built collected every NUTS code in the document, which includes the addresses of all the suppliers. Re-attributed by buyer, Luxembourg is a normal 17.1% with 82 notices. A country can hide inside a supplier's address. (The corrected country table is in the script output; the artifact is the lesson.)

Method, caveats, reproducibility

  • Source: TED monthly packages 2026-7, 2026-8, 2026-9 from ted.europa.eu/packages/monthly/ (fair use: ≤3 concurrent downloads, well under the 700 req/min limit). 213,716 XML files, 0 parse errors.
  • Lag = publication date − earliest stated award date, per notice. All lags are lower bounds (earliest date used; eForms doesn't distinguish "decision" from "contract signed").
  • Sentinels = 2000-01-01, 1970-01-01, 0001-01-01, 7202-01-01, 2001-01-01 = "not stated".
  • Buyer country = first organization in the TED Organizations directory; place-of-performance used as an independent cross-check.
  • Cross-verification: I pulled one notice (00610783-2026, a Faro health authority) and compared the XML totals against the server-rendered TED portal page — 324,530.22 EUR, exact match.
  • One vintage of three months; re-published/corrected notices count separately.

The four scripts (headline stats, notice-type strata, buyer attribution, place-of-performance) rerun on any monthly package in a few minutes each. If you work with EU procurement data, the honest summary is: 44% won't tell you when, ~47% of the rest tell you within the window, and the long tail is mostly framework business — and the single-bid gradient across Europe is real, stable, and apparently nobody else publishes it.

Numbers as of 2026-10-08. One-person studio, small sample of my own mistakes included — this is Pennyforge, and the scripts and corrected tables are the actual deliverable, not the first draft of this analysis.

Top comments (0)