DEV Community

Cover image for How long do you get to bid on a German public tender? I checked 187 notices
Fast Data
Fast Data

Posted on

How long do you get to bid on a German public tender? I checked 187 notices

If you sell to the public sector in Germany, the clock starts the moment a tender is published. So I wanted a simple number: how many days are there between publication and the bid deadline?

I took two daily snapshots (8 and 9 November 2026) of the public tender RSS feed on service.bund.de, the federal portal that also aggregates many state and municipal contracting bodies. After de-duplication that is 195 tenders published between 6 and 9 November. 187 of them state an offer deadline (Angebotsfrist) in the feed.

Disclosure: I built the German Public Tenders actor mentioned at the end. The analysis below uses only the free public RSS feed.

The result

Distribution of days between publication and bid deadline

Days to bid deadline Tenders Share
up to 14 16 9%
15–21 24 13%
22–30 88 47%
31–45 56 30%
over 45 3 2%
  • Median: 30 days. Shortest: 5 days. Longest: 64 days.
  • 40 tenders (21%) give you three weeks or less. That is roughly one in five.

What this means in practice: if you check the portal once a month, you will miss most of the short ones entirely, and you will see the typical 30-day tender with only a week or two left. If public customers matter to you, the check has to be daily, or at least a few times a week.

Is construction faster than IT?

I grouped the titles with a crude keyword match (construction terms like Sanierung, Dach, Elektro, Los 3; IT terms like Software, Lizenz, Server). It is rough, so treat it as a hint, not a finding:

Group (by title keywords) Tenders with deadline Median days ≤ 21 days
Construction 77 30 16
Supplies 18 30 3
Services 13 30 4
IT / software 10 29.5 2
Other / unclear 69 29 15

The medians are almost identical. In this sample, the type of work does not predict the deadline; the individual contracting body does.

Where the tenders come from

German postal codes start with a zone digit, which gives a quick regional picture without parsing addresses:

Postal zone Rough region Tenders
5 Cologne, Bonn, Aachen, Koblenz, Trier 41
0 Saxony, East Thuringia, south Saxony-Anhalt 25
4 Ruhr area, Düsseldorf, Münsterland 24
3 Hanover, North Hesse, parts of Saxony-Anhalt 19
1 Berlin, Brandenburg, Mecklenburg-Vorpommern 12
9 Nuremberg, North Bavaria, most of Thuringia 11
2 Hamburg, Bremen, Schleswig-Holstein 10
6 Frankfurt, Saarland, Mannheim 8
7 Stuttgart, Karlsruhe 6
8 Munich, South Bavaria 4

Careful with this one. Several German states run their own procurement portals, so a low count here means "few of this region's tenders flow into this feed", not "few tenders in this region". If you only watch one portal, you only see part of the market.

Repeat it yourself

The feed is public and needs no key. This script fetches the newest 100 entries and computes the same distribution:

import re, statistics, email.utils, datetime as dt, html
import httpx

FEED = ("https://www.service.bund.de/Content/DE/Ausschreibungen/Suche/Formular.html"
        "?nn=4641482&type=0&resultsPerPage=100&sortOrder=dateOfIssue_dt+desc&jobsrss=true")

xml = httpx.get(FEED, timeout=60, headers={"User-Agent": "tender-deadline-study/1.0"}).text
days = []
for item in re.findall(r"<item>(.*?)</item>", xml, re.S):
    pub = re.search(r"<pubDate>(.*?)</pubDate>", item).group(1)
    desc = html.unescape(re.search(r"<description>(.*?)</description>", item, re.S).group(1))
    m = re.search(r"Angebotsfrist:\s*<strong>(\d\d\.\d\d\.\d{4})", desc)
    if not m:
        continue
    published = email.utils.parsedate_to_datetime(pub).date()
    deadline = dt.datetime.strptime(m.group(1), "%d.%m.%Y").date()
    days.append((deadline - published).days)

print(len(days), "tenders, median", statistics.median(days), "days")
print("3 weeks or less:", sum(d <= 21 for d in days))
Enter fullscreen mode Exit fullscreen mode

Run it once a day and store the result, and after a month you have a much better sample than my four days.

Limits

  • Small sample. Four publication days, one portal. The shape (most deadlines around 30 days, a fat tail of short ones) is plausible, the exact percentages are not a statistic for all of Germany.
  • Feed dates. pubDate is when the notice entered the feed, which can be a day after the official publication.
  • Missing deadlines. 8 of 195 entries had no offer deadline in the feed, only an end of publication.
  • This is not legal or procurement advice. The official notice is what counts.

Try it

If you want the deadline, contracting authority, state, procedure type and CPV codes as clean JSON instead of parsing HTML in RSS descriptions, the German Public Tenders actor does that for $0.002 per tender. For EU-wide notices there is the EU Tenders (TED) API at the same price, and a ready-made n8n workflow that turns both into a daily Slack digest lives in our data-recipes repo.

Question for anyone who bids on public contracts: what is the shortest realistic time you need from "we found it" to a complete bid? I am trying to decide where to set the "urgent" threshold in the alert.

Top comments (0)