Bidefy product document

1. Overview

Live: https://bidefy.vercel.app. API: https://bidefy.iba-jobs.workers.dev/api/v1/health.

Bidefy is tender intelligence for Bangladesh's public procurement portal, e-GP. It indexes every public tender notice and contract award, resolves the messy names of bidders and procuring entities into stable identities, predicts the likely award value of a live tender, flags unusual award patterns with the numbers behind them, and sends web push alerts when a tender matching a subscriber's filters appears.

The gap it fills

Existing services sell daily notice alerts filtered by category, district and organisation, at roughly 1,050 taka a month. None of them use the 877,000 public contract awards on the same portal. So none can answer the questions a bidder actually has: who wins this kind of tender at this entity, at what value, and how often. Bidefy is that layer. It does not compete on alerts.

What is deliberately not built

  • No WhatsApp or Telegram in version one. Web push only, because it costs nothing and needs no Meta account.
  • No payments. The Pro tier shows a request-access form until there is a merchant account.
  • No claim of fraud. Flags describe patterns with counts and intervals, never a verdict.
  • No mirroring of raw notices. The product publishes derived intelligence.

Cost

Production cost is zero. GitHub Actions crawls and trains, Cloudflare Workers and D1 serve the site and send push, GitHub Pages hosts this document and the command centre.

Source facts

Fact Value
Tender notices indexed about 625,800
Contract awards indexed about 877,200
Request rate one per second, one session, checkpointed
Data not published by the portal losing bids, bidder counts, official cost estimates

The tender security amount, which each procuring entity sets as a share of its estimate, is the cost proxy for prediction.

2. Market and competition

Who pays for tender information today

Bangladesh's e-GP portal publishes every public tender notice and contract award without a login. Around it sits a small industry of alert services that re-sell the notices.

Service What it sells Price
BDTender Daily notices by category, district and organisation over email and WhatsApp, plus e-GP training 1,050 taka a month, 8,190 a year, 9,999 premium
AllTender Notices from newspapers, websites and e-GP Subscription
Global aggregators Bangladesh notices bundled into a world feed Foreign-currency subscriptions

None of them use the contract award data. None can say who wins at a given entity, at what value, or how often. That is the layer Bidefy sells.

The buyers

  • Contractors and suppliers bidding on multi-crore tenders. One better-priced bid pays for years of subscription. They already pay the alert services.
  • Companies selling to government, including large groups with tender desks.
  • Banks and lenders that finance contractors against awarded contracts and need a verified award history.
  • Journalists and researchers, who use the free tier and spread the product.

Why not compete on alerts

The alert market has an anchor at about 1,050 taka a month and a lifetime-licence mentality. Bidefy gives the alert layer away and prices the intelligence layer against the value of one contract, not against a competitor's feature table.

What the portal does not publish

Losing bids, bidder counts and official cost estimates are not public. Bidefy predicts award value bands from the security amount, the entity's history and the category, and reports an interval with a deferral rate rather than a point.

3. The system

One pipeline, nightly

  1. Crawl. One request per second against the portal's two public list endpoints, 200 rows a page, checkpointed after every flush, resumed across nights until the index is complete, then a daily delta that stops at the first page with nothing new.
  2. Compact. Small Parquet parts merge into one file once twenty accumulate, so the repository stays a few hundred files rather than thousands.
  3. Resolve. Bidder names are normalised (prefixes such as M/S dropped, punctuation stripped, Bangla combining marks kept), blocked on their first long token, and compared with character n-gram TF-IDF. Pairs at or above 0.92 merge, pairs from 0.80 to 0.92 wait in a review file for a human decision, and every entity gets a stable id from its canonical name.
  4. Fetch details. Every open tender's detail page is fetched, one a second. It carries the portal's own category tags and the refundable tender security, which are the two most valuable fields on the whole portal and appear nowhere in the list pages.
  5. Classify and price. The category is read from those tags where present, and predicted only where it is not. The award band is built from the security where the notice publishes one, and from the entity's history otherwise. Both may decline.
  6. Load. The last twelve months and every live tender go to Cloudflare D1 in statements under 100 KB, budgeted in row writes rather than rows, because every index entry counts as one.
  7. Serve. A Worker answers the API from D1. The site on Vercel renders on the server from that API with short revalidation, so pages are fast and shareable.
  8. Alert. Every hour the Worker takes tenders newer than its watermark, matches them against each subscription's filters, sends web push through the Web Crypto push protocol, records what it sent so nothing repeats, and deletes endpoints that answer 404 or 410.

The deferral principle

A classifier that must answer every time is wrong more often than one allowed to say "not sure". Bidefy publishes accuracy only for the predictions it acts on, and publishes the deferral rate next to it, because a high accuracy with a hidden deferral rate is meaningless. The award-value model follows the same rule: a band with its measured coverage, never a single number, and a decline when the band would be too wide to act on.

How well the models work

Every current figure lives on its own page, What Bidefy gets right, and how often, which is rewritten by each training run so it cannot drift from the model it describes. The short version:

  • An award band built from the tender security published in the notice lands within about 8 percent of the real award value. A band built from the entity's history alone is far looser.
  • A tender's category is read from the portal's own tags for every live tender, so on the live site it is not a prediction at all. The classifier only covers the archive.
  • Both models may decline, and the deferral rate is always printed beside the accuracy.
  • The history band is two quantile models with a conformal pad, not one estimate stretched by a difficulty score. That change alone raised coverage and cut the share of tenders declined, without moving any threshold. What was tried, and what the measurements said has the before and after.

Two lessons worth keeping

A model must not be scored on a rule you wrote. The category model once trained partly on labels produced by a keyword rule inside Bidefy, and was then scored on a test set containing those same labels. It looked accurate. Measured against the portal's own tags it was not, and feeding it twenty thousand keyword labels drove real accuracy from 89.8 percent to 55.4 percent. The labels were removed.

Read the answer before predicting it. The portal publishes category tags on each tender's detail page, and a tender security that is a fixed share of the buyer's own cost estimate. Fetching those pages turned the category from a prediction into a lookup, and cut the award band from roughly eleven times wide to about one and a half. Most of the accuracy came from collecting better evidence, not from a better model.

Budgets that shape the design

Budget Value Consequence
Portal politeness 1 request per second, one session Full index takes an hour from Dhaka, several nights from a US runner
D1 writes 100,000 a day, and every index entry counts as a write Budget kept in writes, not rows: a tender row costs five. Awards never go in as rows; bidder and entity profiles carry JSON aggregates. 80,000 writes a day across both runs, tracked in the watermark
D1 statement size about 100 KB Byte-aware batching, roughly 150 rows per statement
GitHub Actions 6 hours per job 300-minute crawl budget, checkpoint and resume
Push per subscription 20 per hourly run A noisy filter cannot flood a phone

What is not built, on purpose

No WhatsApp, no payments, no fraud verdicts, no mirror of raw notices, no losing-bid data because the portal does not publish it.

4. Five buyer profiles

These profiles are computed from public award data, not interviews. Each is a real bidder selected by a fixed rule; the rule is stated so the selection can be reproduced.

Known limit: bidders are resolved by name, so a common trade name can combine several firms. The generalist rule therefore requires a footprint of three districts or fewer. Award values above 500 crore were keyed in taka on the portal and are converted to crore; no genuine award in the index is that large.

The specialist: Md. Zinnat Hossain Biswas

  • Rule: most awards at a single procuring entity (Faridpur Road Division, 115 awards).
  • Awards indexed: 418, total value 120.89 crore
  • Entities: 44, districts: 40
  • Main categories: roads_bridges, buildings_civil

What Bidefy shows them: Every new tender from that entity within the hour, the entity's award history, and the value band before they price.

The generalist: A.K. International

  • Rule: awards under 5 or more ministries, most awards among them.
  • Awards indexed: 72, total value 4.98 crore
  • Entities: 28, districts: 1
  • Main categories: buildings_civil, electrical_power

What Bidefy shows them: Category filters across ministries and a single feed instead of five portals' worth of notices.

The infrastructure contractor: M. M. Builders & Engineers Ltd.

  • Rule: highest total award value in the last twelve months (1208.37 crore across 8 awards).
  • Awards indexed: 12, total value 1525.04 crore
  • Entities: 8, districts: 7
  • Main categories: roads_bridges, it_equipment

What Bidefy shows them: Who else wins at the entities they target, the concentration flags, and bands on multi-crore tenders where one mispriced bid costs more than a year of Pro.

The newcomer: Bangladesh Milk Producers' Co-operative Union Limited

  • Rule: first indexed award within the last 90 days, most awards since (72).
  • Awards indexed: 72, total value 4.02 crore
  • Entities: 72, districts: 64
  • Main categories: food_catering, it_equipment

What Bidefy shows them: Which entities award to newcomers, and the typical value at their size, so they bid where they can win.

The regional bidder: M/S G.M. INTERNATIONAL

  • Rule: highest share of awards in one district (Dhaka, 100% of 97).
  • Awards indexed: 97, total value 26.34 crore
  • Entities: 6, districts: 1
  • Main categories: electrical_power, buildings_civil

What Bidefy shows them: District-filtered alerts and the entities in their district ranked by volume.

Pricing signal: the first three profiles bid on tenders where a one percent pricing error exceeds 2,500 taka. The last two are free-tier users until they grow.

5. A primer on Bangladesh public procurement

Written for the owner before an interview, and for anyone reading Bidefy who has never bid on a tender. Everything here is what the site assumes you know.

What a tender is

A tender is how a public body buys without picking a favourite. The buying office, called the procuring entity, publishes what it needs, when bids close, and the rules. Firms submit sealed, priced offers. A committee opens them after closing, checks each bid is complete and eligible, and for most goods and works awards the contract to the lowest responsive price. The buyer then publishes a Notification of Award naming the winner and the value, and signs the contract.

In Bangladesh this runs on one portal, e-GP, owned by the Bangladesh Public Procurement Authority under the Public Procurement Act 2006 and Rules 2008. Around 90 percent of public purchasing by volume goes through it. Every notice, correction and award is public without a login. That is the fact Bidefy is built on.

How to read a tender notice

Field on the notice What it means What Bidefy does with it
Tender id e-GP's number for the notice The key for everything
Reference number The buyer's own file number Shown for matching paperwork
Procuring entity The office buying and signing Profile page with award history and concentration
Ministry, division, organisation The layers above the entity Filters and the award model
Nature Goods, Works or Services Shown on cards
Method How bids are invited (see below) Tooltip, model feature
Type NCT for national, ICT for international bidders Tooltip
Publishing and closing The bidding window Days-left badge, alerts
Tender security Refundable deposit, a fixed share of the buyer's secret cost estimate Proxy for tender size in the award model
Document price Fee for the full document Shown on the detail page
Category tags The portal's own classification, only on the detail page Training labels for Bidefy's category classifier

The procurement methods

  • OTM, Open Tendering. Anyone eligible may bid. The default for anything sizeable. Most of what Bidefy indexes.
  • LTM, Limited Tendering. Only enlisted firms are invited. Smaller or specialised buys.
  • RFQ, Request for Quotation. Quick quotes for low-value items, short deadlines, thin paperwork.
  • DPM, Direct Procurement. One supplier, no competition, allowed in defined cases such as emergencies or proprietary parts.
  • OSTETM and TSTM. Two-envelope and two-stage variants for complex procurements where the technical offer is judged before the price is seen.

What the statuses mean

Live means bids are being accepted. Being processed means closed and under evaluation. Contract Awarded means a winner has signed. Cancelled and Rejected end the process; Re-Tendered means the buyer will try again, usually because too few valid bids arrived. Corrigendum means a published correction, often a new closing date; Bidefy shows that note separately from the status.

Money

Values are stated in crore. One crore is ten million taka, one lakh is a hundred thousand, so one crore is a hundred lakh. Bidefy shows amounts under one crore in lakh. The median award in the index is about eleven lakh; one in ten is above 1.2 crore. On the portal some values are keyed in taka by mistake; Bidefy converts anything above 500 crore, because no genuine award in the index is that large.

What the buyer never tells you

The buyer's cost estimate, the losing bids and the number of bidders are not published. That is why Bidefy predicts a band rather than reporting one, and why the tender security matters: it is the only public number tied to the estimate.

The five questions a bidder asks

  1. Is there a tender I should see today? Alerts by keyword, ministry, category, status.
  2. What has this entity paid for this kind of work? The band, and the entity's recent awards.
  3. Who usually wins here? The entity's top bidders and the share the leader holds.
  4. Is this entity worth my time? Concentration flags: if one firm has won 80 percent of the last twelve months, the odds are stated, not hidden.
  5. Who am I up against? Bidder profiles with award history, entities, districts and categories.

What Bidefy refuses to claim

A pattern is not a verdict. A concentrated entity may simply have one competent local supplier. Bidefy publishes shares and counts and lets the reader decide. The award model publishes its error and its deferral rate together, and declines when the band would be too wide to act on. The category classifier does the same.

Two sentences for an interview

Bidefy reads the public procurement portal every night, resolves 28,000 bidders from 210,000 awards, predicts what an entity will pay with a calibrated band, and alerts a bidder within the hour. It is free at the alert layer and priced at the intelligence layer, and it declines to answer when it cannot answer honestly.

6. What Bidefy gets right, and how often

Every figure here is measured on data the model was not trained on, and this page is written by the training run itself, so it cannot drift from the model it describes.

Two rules govern everything below. A model may decline, and when it declines that is reported next to its accuracy, because an accuracy figure without its deferral rate is not a measurement. And a prediction is only scored against evidence the model could not have seen: the portal's own records, never a rule Bidefy wrote.

Award value

The history route is trained on 546,033 awards, calibrated on 327,620 out-of-sample residuals, and scored on the 136,579 most recent awards, everything signed on or after 2025-06-24. Every award it is scored on is later in time than every award used to fit or calibrate it, so this is a forecast, not a fit.

A tender notice publishes a refundable tender security. Buyers set it as a fixed share of a cost estimate they do not publish, and awards land near that estimate, so where a security exists it pins the value far more tightly than history can.

The two routes are measured on two different windows, and are never averaged into one headline. The archive of awards reaches back years, but detail pages have only been fetched for roughly the last year, so every published security on record is recent. Split the whole archive by date and all of them land after the cut, leaving the security multiplier nothing to learn from. So that route is given its own split, at eighty percent of the securities by date, fitted on the earlier ones and scored on the later ones. Both windows are strictly forward-looking.

From the tender security From entity history
Awards scored 423 105,039
Fitted on 1,673 earlier securities 546,033 earlier awards
Scored on awards signed from 2026-08-04 2025-06-24
Median error of the central estimate 8.7 percent 37.9 percent
Share of awards inside the band 79.7 percent 78.6 percent
Typical band, high over low 1.42x 5.09x

Of the 2,096 awards in the archive whose notice published a security, that is every one the route could be scored on without fitting and testing on the same rows.

What a bidder actually meets

Of the tenders open right now, 80.0 percent publish a security and take the precise route; the rest fall to history. The archive is a poor guide to that split, because its detail pages were mostly never fetched, so a security looks absent there when it was only uncollected. Weighting the two measured routes by the split the site actually serves:

Route Share of open tenders Median error Typical band
From the tender security 80.0 percent 8.7 percent 1.42x
From entity history 20.0 percent 37.9 percent 5.09x

Four tenders in five get the precise answer. That is a property of what the portal publishes, not of the model, and it is the single most valuable thing found in this project. Nothing here is an average of the two rows: each is measured on its own held-out window and reported as itself.

Taking the test window exactly as crawled, with whatever mix of routes it happens to contain, the median error is 37.0 percent and the typical band is 5.02x wide. For scale, the spread between the 10th and 90th percentile of all awards is 56x, which is the band someone would quote knowing nothing at all. Simply guessing the median award for every tender gives a median error of 79.5 percent.

The history route is not one number

Open tendering is the hardest method to price and the one the history route is mostly asked about, because a large open tender is exactly the kind that publishes no security. Quoting a single history figure would hide that, so here is each method on its own.

Method Tenders answered Median error Inside the band Typical band Declined
LTM 53,453 32.2 percent 81.2 percent 4.26x 6.3 percent
OTM 40,133 45.3 percent 75.4 percent 6.19x 31.4 percent
RFQU 6,132 43.0 percent 78.9 percent 6.26x 30.1 percent
RFQ 4,299 42.9 percent 77.3 percent 5.3x 45.9 percent
DPM 446 69.5 percent 71.5 percent 7.16x 28.9 percent
RFQL 403 46.0 percent 86.4 percent 6.55x 53.1 percent
OSTETM 129 57.0 percent 67.4 percent 9.31x 76.3 percent

Bidefy declines when a band would be too wide to act on. Where that line is drawn is a product decision, not a statistical one, so here is the whole trade:

Widest band shown Tenders declined
4x 73.6 percent
6x 48.8 percent
8x 32.0 percent
12x 15.8 percent
20x 5.1 percent

Category

A tender's category is read from the portal's own tags wherever Bidefy has fetched that tender's detail page. The model below exists only to cover tenders whose detail page has not been fetched, mostly older archived ones.

Of the 3,405 tenders open right now, 85.2 percent take their category straight from the portal. For those the category is not a prediction at all, and nothing is declined.

Trained and scored on 6,640 tenders across 15 categories, cross-validated on portal category tags only, entity priors from the training fold.

Measure Value
Accuracy on the predictions it commits to 93.0 percent
Share of tenders it declines 44.7 percent
Accuracy if forced to answer every time 75.9 percent
Macro F1 across categories 0.639
Deferral needed to reach 93 percent 44.7 percent
Deferral needed to reach 95 percent 52.2 percent

This model is not deterministic. Run the same cross-validation again, on the same data with the same seed, and the share it declines moves by up to 0.5 percent and its macro F1 by 0.016. That is the floor below which a change to this model cannot be distinguished from chance, and it is published here because a figure quoted without it invites reading an improvement into noise. The numbers above pool 3 runs, which is why they are steadier than any one of them.

What would move these numbers

The award band is limited by what a notice says. The title carries the item but rarely the quantity, and the quantity lives in a tender document behind a fee. Fetching the detail page of every live tender is what unlocks the security route, and that is now part of the nightly run. The category model is limited by labelled examples, and every detail page fetched adds one.

An earlier version of the category model also trained on labels produced by a keyword rule Bidefy wrote. Removing them was worth doing: adding twenty thousand such rows had driven accuracy against the portal's real tags from 89.8 percent down to 55.4 percent, while making the published figure look better, because the model was partly being scored on the rule it had been taught to copy.

7. What was tried, and what the measurements said

A model is only trustworthy if the things that did not work are written down beside the things that did. Every row below is an experiment run on the real data, with the evaluation population held fixed so the comparison is about the change and nothing else.

Two rules were applied throughout. No result counts if it came from moving a confidence threshold or a band-width cutoff, because that trades one published number for another without the model getting better. And no result counts if the change altered which tenders were being scored, because a model can always look better by being asked easier questions.

Award value

The award model answers with a band, and reports what share of real awards landed inside it.

Every comparison in this section was run on the same 210,544-award extract, so the arms differ only by the change under test. The crawl has since more than tripled that archive, to 682,612 awards, and the figures published on the accuracy page come from the full set. A number here will therefore not match one there; what carries across is the direction and size of each change, not its level.

Change Median error Inside the band Band width Declined Kept
Band scaled by a predicted difficulty 33.9 percent 77.1 percent 4.60x 27.9 percent replaced
Band calibrated per method and per size 33.7 percent 77.0 percent 4.70x 28.3 percent no
Band calibrated per size alone 34.7 percent 77.1 percent 4.95x 25.2 percent no
Two quantile models, conformalised 34.8 percent 79.6 percent 4.89x 21.4 percent yes

Splitting the calibration by size did nothing. The idea was that a small purchase and a large one are not equally predictable, so one shared band serves neither. Measured, it moved coverage by a tenth of a point and cost width. Rejected.

Replacing the difficulty scale with two quantile models worked. The old band took one central prediction and stretched it by a predicted difficulty, which assumes every tender's error has the same shape, only wider or narrower. Real awards are not like that: a tender can have a firm floor and a long tail above it. Fitting one model to the low edge and one to the high edge, then padding both by a conformal margin, lets the two edges move independently.

It answered 31,891 of the test tenders instead of 29,107, and covered more of them. The median error rose from 33.9 to 34.8 percent, and that rise is composition, not decay: the central estimate comes from the same model in both, so the only reason the error moved is that 2,784 tenders it used to decline are now answered, and those are the hard ones.

Giving the model the buyer's own past price level

The model already had the buyer as a category, so in principle it could learn what each one pays. In practice it has to learn that level by level from whatever rows it happens to see, and most buyers are rare. Handing it the running average of what this buyer has paid before, and what it has paid before under this same procurement method, is the same evidence in a shape it can use. Only awards signed earlier count, so no tender is ever informed by its own outcome.

Without With
Tenders answered by the history route 31,891 32,136
Median error 37.0 percent 36.6 percent
Inside the band 79.4 percent 79.4 percent
Typical band 5.06x 4.92x
Declined 21.4 percent 20.8 percent

Every figure moves the right way at once, which is what separates a real effect from noise: a coincidence moves some up and some down. It answers more tenders, with narrower bands, at the same coverage. The drop in declines is about three times its own sampling error. Kept.

The tender document price is not a second security

A notice publishes two prices the buyer chose: the refundable security, and the fee to download the tender document. The security is a fixed share of the buyer's cost estimate, which is why it pins the award so tightly. The document fee looked like it might be a second such signal, and it is published more often than the security is.

It is not. Across 2,418 awards that published one, the ratio of award to document fee runs from about 570 at the tenth percentile to 7,230 at the ninetieth, a spread of 12.7 times. The security's ratio spans 1.5 times over the same range. Pricing an award straight off the document fee gives a median error of 51 percent, worse than the history route it would have replaced. The fee is set on coarse value slabs, so it says which bracket a tender is in and almost nothing more. Rejected.

Category

First, how much does this model move when nothing changes?

Everything below rests on this number, and it should have been measured first. Running the same cross-validation three times, on the same data, with the same seed, gives these deferral rates:

Run Declines Macro F1
1 44.41 percent 0.658
2 45.06 percent 0.649
3 46.11 percent 0.642

A spread of 1.7 points of deferral and 1.6 points of macro F1, from nothing at all. The training is not bit-reproducible, and the deferral threshold is chosen at a percentile of a confidence distribution, so a difference in the last decimal place of a probability moves which tenders fall either side of the line.

Pinning every maths library to a single thread was the obvious suspect, and it is only half the story: single-threaded, the deferral rate repeats exactly, but macro F1 still moves 1.3 points between two identical runs. Correctness is stable while the identity of the wrong answer is not, so predictions on near-ties still shift, and macro F1 reads those shifts. Single-threading would cost several times the training time and still leave macro F1 unstable, so the fix is to pool runs rather than chase bit-reproducibility.

That is the floor. Any change to this model worth less than about two points is indistinguishable from chance on a single run, and several comparisons made earlier in this project were inside it and should not have been called results. The model now pools three runs for every published figure and prints the spread beside them.

Training only on the decisive labels makes it much worse

The portal's tags are noisy, so the obvious move is to train only on labels that won by a clear margin of keywords and keep scoring on all of them. Discarding the 23 percent of labels decided by a single keyword against a close second:

Every label Decisive labels only
Declines at 93 percent accuracy 44.4 percent 53.3 percent
Macro F1 0.648 0.577
Accuracy if forced to answer 76.0 percent 71.9 percent

Nine points of deferral and seven of macro F1, far outside the noise floor. The labels that look weakest still carry more signal than the rows are worth losing. Rejected, and worth remembering: the first version of this experiment had a guard that silently refused to apply the filter at all, so it produced three sets of numbers that differed only by the noise above and looked like a mild improvement. The guard was found only because the arms should have been bit-identical and were not.

Does the buyer's own history still help? No longer measurably

A hospital does not buy bridges, so who is buying is evidence about what is being bought, and this model multiplies its text probabilities by the buyer's own category history. That was worth several points of deferral when the label set was smaller. With 6,640 labels, and each measurement pooling three cross-validations:

Without the buyer's history With it
Declines at 93 percent accuracy 45.1 percent 44.8 percent
Macro F1 0.643 0.646
Accuracy if forced to answer 75.8 percent 75.6 percent

Three tenths of a point, against a run-to-run spread of eight tenths to nearly two points. The honest reading is that the feature no longer earns its place on the evidence available, and that an earlier version of this comparison, which put its value at nine tenths of a point, was reading noise. It is kept because it costs nothing and was genuinely useful at a smaller label set, not because this measurement supports it. Worth retesting when the label set doubles.

What limits this model is the label, not the model

The portal's category tags are the only honest ground truth available, and they are themselves noisy. A tender carries a median of 27 tags, and where a tender's own description also resolves to a category, it agrees with the tag-derived label only 50.3 percent of the time across 3,626 tenders.

That is the thing to fix. It does not make the reported accuracy wrong, since it is measured against those tags either way, but it does mean a large share of the apparent mistakes are cases where the tags and the tender's own words disagree, and no amount of modelling resolves that from the inside.

What the larger archive did to the headline

Retraining on 682,612 awards rather than 210,544 moved the security route's coverage from 83.9 percent to 79.7 percent, and left its median error and band width where they were, at 8.7 percent and 1.42 times. The coverage did not fall because the model got worse. It fell because the route is now scored under a stricter rule.

Every published security in the archive is recent, since detail pages have only been fetched for about the last year. Split the whole archive by date and all of them land after the cut, so the multiplier has nothing to learn from and the route switches itself off entirely, which is what the first full-archive run did: zero securities scored. The route now gets its own forward split, fitted on 1,673 earlier securities and scored on the 423 signed later. Coverage of 79.7 percent against a target of 80 is a band doing exactly what it promises. The earlier 83.9 percent was a band quietly wider than it needed to be.

What an archived detail page is actually worth

The security route is so much better than the history route that the obvious move is to fetch detail pages for tenders that have already been awarded, not just for open ones, so the model has more of them to learn from. Only 5,794 of the 125,136 awards signed since September 2025 had been fetched.

The first 603 pages of that crawl say what the rest will cost. The portal no longer serves every archived page in full:

Out of 100 archived award pages fetched
Come back as a stub, with nothing on them 41
Come back complete 59
Carry category tags 59
Publish a security 38

So roughly five requests buy three usable pages. An earlier estimate put the security rate at 85 percent, taken from open tenders, and open tenders are not a fair guide: they are current, and the portal serves them whole. Against archived awards the rate is 38 per hundred fetched.

The lever is still much the largest available. Fetching the remaining 119,342 awards in the window would add roughly 45,000 securities against the 2,096 on record, and roughly 70,000 category labels against 6,640. It is a twentyfold increase in the evidence behind the precise route and a tenfold increase in the category training set, and it needs no modelling at all. At one request a second it is about 33 hours of crawling, which is why it now has an hour of every nightly run.

The two rejected ideas worth remembering

Keyword labels. Adding twenty thousand labels from a keyword rule raised the published accuracy and destroyed the real one, from 89.8 percent to 55.4 percent against the portal's own tags, because the model was partly being scored on the rule it had been taught to copy.

Richer text features and finer security multipliers. Both were tried, neither moved a number outside its noise, and both were reverted rather than kept for the sake of having changed something.