Okay, I have some data from @miketheman (thanks Mike!) on how often this behavior is used:
warehouse=> SELECT
COUNT(DISTINCT p.id) FILTER (WHERE f.upload_time - r.created >= INTERVAL '14 days') AS days_14,
COUNT(DISTINCT p.id) FILTER (WHERE f.upload_time - r.created >= INTERVAL '7 days') AS days_7,
COUNT(DISTINCT p.id) FILTER (WHERE f.upload_time - r.created >= INTERVAL '3 days') AS days_3,
COUNT(DISTINCT p.id) FILTER (WHERE f.upload_time - r.created >= INTERVAL '2 days') AS days_2,
COUNT(DISTINCT p.id) FILTER (WHERE f.upload_time - r.created >= INTERVAL '1 day') AS days_1
FROM
projects p
INNER JOIN releases r ON r.project_id = p.id
INNER JOIN release_files f ON f.release_id = r.id
WHERE
DATE_PART('year', r.created) >= 2025;
days_14 | days_7 | days_3 | days_2 | days_1
---------+--------+--------+--------+--------
1295 | 1611 | 2008 | 2188 | 2478
So in the past ~year, there have been 1295 projects that have published an artifact 14+ days after the initial release and many more happening in the 1-3 day span. So if we were to implement the 14 day policy there would be 2-3 projects per day that would see the new error until the community “routed around” the error by creating new releases, instead.
Mike also provided a few example projects where this happened over the last ~5 years:
warehouse=> WITH classified AS (
SELECT
p.normalized_name,
r.version,
f.upload_time - r.created AS lag,
CASE
WHEN f.upload_time - r.created >= INTERVAL '14 days' THEN '14+'
WHEN f.upload_time - r.created >= INTERVAL '7 days' THEN '7-13'
WHEN f.upload_time - r.created >= INTERVAL '3 days' THEN '3-6'
WHEN f.upload_time - r.created >= INTERVAL '2 days' THEN '2'
WHEN f.upload_time - r.created >= INTERVAL '1 day' THEN '1'
END AS bucket
FROM
projects p
INNER JOIN releases r ON r.project_id = p.id
INNER JOIN release_files f ON f.release_id = r.id
WHERE
DATE_PART('year', r.created) >= 2021
AND f.upload_time - r.created >= INTERVAL '1 day'
),
ranked AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY bucket ORDER BY random()) AS rn
FROM classified
)
SELECT bucket, normalized_name, version, lag
FROM ranked
WHERE rn <= 10
ORDER BY bucket, rn;
bucket | normalized_name | version | lag
--------+------------------------------------------+-------------+--------------------------
1 | ensmallen | 0.8.76 | 1 day 00:10:45.922215
1 | cmarkgfm | 2025.10.20 | 1 day 01:27:05.343397
1 | libfsapfs-python | 20220501 | 1 day 14:05:15.12519
1 | passagemath-graphs | 10.6.42 | 1 day 07:17:19.996306
1 | fast-bencode | 1.1.6 | 1 day 14:58:30.727354
1 | ros-sensor-msgs | 5.3.6 | 1 day 20:32:41.263156
1 | sccache | 0.8.2 | 1 day 10:40:01.020694
1 | thirdai | 0.9.33 | 1 day 09:56:05.610839
1 | rscheduler | 0.1.0 | 1 day 07:11:43.045616
1 | signalflow | 0.5.3 | 1 day 02:42:15.365097
2 | g2o-python | 0.0.3 | 2 days 01:12:39.599578
2 | libfvde-python | 20240502 | 2 days 12:57:30.880789
2 | passagemath-rankwidth | 10.6.30 | 2 days 06:26:43.426063
2 | netgen-mesher | 6.2.2306 | 2 days 02:08:19.66846
2 | poselib | 2.0.0 | 2 days 00:07:12.73351
2 | passagemath-meataxe | 10.6.31rc3 | 2 days 22:00:14.091101
2 | llama-cpp-cffi | 0.1.2 | 2 days 16:37:21.36003
2 | pymatio | 0.1.0 | 2 days 12:32:45.487768
2 | kratosgeomechanicsapplication | 9.4.3 | 2 days 20:02:06.617887
2 | note-scoring | 0.1.0 | 2 days 09:54:10.648191
3-6 | libevtx-python | 20240504 | 3 days 02:38:41.990573
3-6 | bosa-connectors-binary | 0.0.10 | 4 days 07:02:42.279023
3-6 | nessie-py | 0.1.7 | 3 days 06:05:31.521771
3-6 | graph4nlp-cu110 | 0.2a4 | 3 days 22:24:18.7649
3-6 | mandelbrot-implementations-cython-direct | 0.1.0 | 6 days 20:47:03.090528
3-6 | pillow | 8.3.1 | 4 days 22:10:28.756944
3-6 | gamsapi | 49.6.1 | 3 days 06:32:15.66552
3-6 | rocksdict | 0.3.24 | 3 days 03:44:11.150153
3-6 | fast-dep | 0.0.1 | 4 days 12:16:08.354373
3-6 | trust-free | 2.1.4 | 3 days 20:34:26.858133
7-13 | python-sat | 0.1.8.dev13 | 10 days 05:04:46.601852
7-13 | ros-unique-identifier-msgs | 2.5.0 | 8 days 19:42:51.64209
7-13 | mlpack | 4.7.0 | 9 days 03:24:38.198048
7-13 | ytsaurus-yson | 0.4.5 | 7 days 18:37:11.562206
7-13 | google-re2 | 1.0 | 12 days 00:05:13.312822
7-13 | instanttensor | 0.1.6 | 12 days 20:42:33.076557
7-13 | opencv-contrib-python-headless | 3.4.14.51 | 12 days 19:21:55.810543
7-13 | google-re2 | 1.0 | 12 days 00:05:19.726237
7-13 | dlblas | 0.0.2 | 7 days 08:48:55.218678
7-13 | pyhyperscan | 0.1.9 | 10 days 22:54:47.973345
14+ | xmlib-to-git | 1.0.0 | 474 days 18:57:09.411265
14+ | tensorflow-metal | 0.8.0 | 45 days 14:21:08.78746
14+ | rs-audio-stats | 1.3.9 | 134 days 17:27:47.292922
14+ | dlib-bin | 19.24.6 | 147 days 10:42:54.269826
14+ | abstract-utilities | 0.2.0.58 | 40 days 20:39:22.917332
14+ | pyzstd | 0.15.0 | 106 days 17:25:03.286604
14+ | opening-hours-py | 0.9.1 | 29 days 19:33:15.477529
14+ | sbank | 1.0.2 | 726 days 14:19:53.907989
14+ | pr2codon | 1.1.18 | 722 days 10:33:47.026539
14+ | hmpty | 1.5.10 | 571 days 23:20:35.227465
(50 rows)
I do see a few names I recognize in this list: Pillow, google-re2, pyzstd. Looking at a few of the examples, I see many of the longer durations being “adding wheels after only having sdists” and the medium length durations being “adding wheels with different platforms”.