Three supplier contracts auto-renewed in March at a 30-person UK professional services firm, and nobody in the business was alerted. Two carried annual price escalation clauses of 4.5% and 6.2%. The ops director spotted it on the invoice, two months into the new term, and the missed renegotiation window cost £28,000 across the 12-month renewal periods. Their contract store was a shared drive folder of 47 PDFs, one spreadsheet last updated in October 2022, and no contract renewal software watching any renewal date.
We've seen this at five UK SMEs in the past year. The specific contract varies (software licence, cleaning contract, outsourced HR retainer), but the mechanism is identical each time.
How many UK SME supplier contracts auto-renew unreviewed, and what it costs
The Chartered Institute of Procurement & Supply's 2024 contract management survey found that 34% of supplier contracts at UK SMEs had auto-renewed at least once without a formal review: a third of ongoing supplier relationships running on pricing last negotiated years ago.
The financial exposure compounds. A 50-person firm carrying 30 active supplier contracts averaging £15,000 per year is managing £450,000 in annual supplier spend. If a third of those auto-renew unreviewed, and half carry escalation clauses averaging 5%, that is roughly £22,500 in avoidable annual cost increases from clauses already written into existing documents.
Contract renewal tracking does not exist in that setup. A shared drive folder has no mechanism to surface "this contract expires in 60 days." A spreadsheet works until the person maintaining it leaves, or until a new contract gets filed without updating the sheet. Most spreadsheet-based approaches drift into unreliability within six months.
Extracting renewal dates, notice periods and escalation clauses from PDF agreements
The ingestion pipeline takes a PDF supplier agreement and produces a structured JSON record. Here is the extraction prompt pattern we use with Claude claude-3-5-sonnet. The same approach drives our invoice data extraction pipeline.
EXTRACTION_PROMPT = """
You are extracting structured data from a UK supplier contract.
Return JSON only. No commentary.
Fields to extract:
- renewal_date: ISO 8601 date string or null
- notice_period_days: integer or null
- auto_renewal: boolean
- price_escalation_clause: boolean
- escalation_mechanism: string describing the escalation formula/index, or null
- initial_term_months: integer or null
- governing_law: string (e.g. "England and Wales")
- notice_method: string (e.g. "written notice by recorded post", "email to [email protected]")
- key_obligations: list of strings, max 5
Contract text:
{contract_text}
"""
The pipeline runs in four stages:
- PDF extraction: pypdf for text-layer PDFs; Azure Document Intelligence for scanned documents or image-heavy formats.
- Chunking: split to approximately 4,000 token chunks with 200-token overlap, keeping page boundaries intact where possible.
- LLM extraction: each chunk passes through the extraction prompt; results are merged with a conflict-resolution pass that uses a majority vote when the same field appears with different values across chunks.
- Confidence scoring: dates with ambiguous formats such as "12/06/2024" (December or June?) get flagged for human review before ingestion.
Notice periods are the field that causes the most extraction errors in practice. Contracts often express them indirectly: "the parties agree that renewal notices shall be served no fewer than ninety days prior to the then-current term expiry." That sentence parses to 90 days, but the LLM needs to correctly identify "then-current term expiry" as the anchor date, not the contract start date. About 8% of contracts in our pipeline require manual review of the notice period field specifically.
Obligations buried in schedules and exhibits
The main contract body gets the attention. Schedules do not. We have extracted obligations from contracts where Schedule 4 required the supplier to provide quarterly performance reports, and the buyer had three years of missed deliverables they had never chased because nobody knew the obligation existed.
Obligations that create buyer-side liability typically appear as: - Minimum purchase commitments: "Buyer shall place orders totalling no less than £X per quarter" - Audit rights with time limits: "Buyer may audit records within 12 months of invoice date" - Data handling requirements that carry ICO enforcement exposure if missed - TUPE obligations triggered by contract termination, which often appear in schedule-level clauses rather than the main body
Our obligation extractor runs a separate extraction pass specifically on schedules and exhibits, treating each as its own document segment and tagging extracted obligations with their source page and schedule reference. When an obligation surfaces in an alert, the ops lead sees the verbatim clause alongside our interpretation of it. Both matter, because "what we extracted" and "what the clause actually says" occasionally diverge, and the ops lead needs to catch that.
Separating obligation extraction from renewal date extraction matters: running both in a single prompt produces lower accuracy on both. Two focused prompts, merged at the database layer, performs measurably better on our test set of 200 UK supplier contracts.
Alert design: how far ahead of notice expiry to trigger review, and who gets it
Contract renewal reminder software lives or dies on timing. Too early and the alert becomes background noise; too late and there is no time to renegotiate meaningfully.
Our default alert schedule for a contract with a 90-day notice period:
| Alert | Trigger | Recipient | Channel |
|---|---|---|---|
| Initial review | T−90 days | Contract owner | Email + Slack |
| Decision prompt | T−60 days | Contract owner + line manager | |
| Final warning | T−30 days | Contract owner + Finance | Email + Slack (urgent tag) |
| Missed window | T+1 day past notice deadline | Finance director |
The "missed window" alert is deliberate. When the notice period expires without a confirmed action logged, the Finance director gets a direct message explaining the contract will auto-renew and attaching the contract summary. Accountability without requiring perfect upstream behaviour.
Alert routing also requires a named contract owner field populated at ingestion. If every contract defaults to a shared group address, every alert goes to one inbox and gets treated as general FYI. Assign a named individual at ingestion (the person who negotiated the contract or currently manages the supplier relationship) and route the first alert to them directly.
The renewal brief: renegotiation context for the ops lead in 90 seconds
When the first alert fires at T−90, it includes a renewal brief: a one-page summary generated from the extracted contract data. The brief covers:
- Current pricing and the escalation formula, with the calculated price if the contract auto-renews at the clause rate
- The supplier's performance record against any SLAs in the contract, pulled from the ticketing or finance system via API
- The notice deadline and the specific notice method required by the contract
- Three clauses flagged for potential renegotiation, based on escalation, liability cap, and minimum commitment fields
We use a separate summarisation prompt rather than asking the extraction model to produce both structured data and human-readable prose in one pass. The extractor produces structured JSON; the summariser reads that and the extracted clause text to produce the brief. Separating the two prevents hallucination from cascading: a field-level error surfaces as an anomalous JSON value rather than being embedded in prose the ops lead trusts as authoritative. The brief attaches as a PDF to the alert email and links from the Slack notification.
For similar summarisation patterns applied to internal knowledge management, see our Document RAG case study.
Contract management software for small business: the schema behind 200 agreements
The metadata schema drives everything downstream. Here is the Postgres table definition we use for contract records:
CREATE TABLE contracts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
supplier_name TEXT NOT NULL,
contract_reference TEXT,
contract_type TEXT, -- 'software', 'services', 'goods', 'facilities'
signed_date DATE,
initial_term_months INTEGER,
renewal_date DATE,
notice_period_days INTEGER,
auto_renewal BOOLEAN DEFAULT TRUE,
escalation_clause BOOLEAN DEFAULT FALSE,
escalation_mechanism TEXT,
current_annual_value_gbp NUMERIC(10,2),
contract_owner_email TEXT,
status TEXT DEFAULT 'active', -- 'active', 'review', 'terminated', 'expired'
pdf_s3_key TEXT,
extracted_at TIMESTAMPTZ,
extraction_confidence TEXT, -- 'high', 'medium', 'low'
last_human_review TIMESTAMPTZ,
CONSTRAINT valid_status CHECK (status IN ('active', 'review', 'terminated', 'expired'))
);
The extraction_confidence field does real work. Low-confidence extractions route to a human review queue before they drive alerts. Approximately 8% of contracts have unusual formatting or obfuscated renewal terms, particularly software licensing agreements, that require a manual check. The same review-queue pattern is covered in our post on human-in-the-loop OCR.
At 50–200 contracts, Postgres is sufficient, which makes a custom build a fair alternative to off-the-shelf contract management software in the UK. Contract renewal management software and a custom build both need the same four things: a reliable extraction pipeline, this table schema, a daily scheduled job checking for approaching notice deadlines, and a notification handler that routes to named individuals. You do not need a purpose-built contract lifecycle management platform. We build this under our workflow automation service.
For the full pipeline architecture on document processing, see our invoice OCR pipeline case study; many of the same patterns apply.
Routing renewal alerts through Slack, email and project tools
The extraction and storage layer is the easier problem. Getting alerts to the right person, through the right channel, at the right time is where most implementations break down.
What fails in practice: - Group email ("ops@"): alerts get treated as informational, no one is assigned responsibility, and they expire in a shared inbox. - Slack-only alerts get buried in channel history within 48 hours, especially in busy general operations channels. - Project tool tickets without assigned owners — same failure mode as group email: visible in aggregate, invisible to any one person.
What works: the named contract owner gets the first alert by direct email, with a copy to their line manager at T−60. The Slack alert goes to a dedicated #contracts-review channel and tags the owner directly. The ClickUp or Asana task is assigned to that individual with a due date 7 days before the notice deadline. It turns overdue if no action is taken, creating a paper trail either way.
For the related problem of extracting structured obligations from shorter legal documents, see our post on LLM contract review for UK SME NDAs and commercial agreements.
The Procurement Act 2023 and notice period norms
The UK Procurement Act 2023, which came into full effect for central government contracts in February 2025, introduced new transparency requirements and more explicit auto-renewal provisions in standard public sector contract templates. The downstream effect for private sector SMEs who supply to public sector buyers has been real: notice periods in public sector-adjacent contracts have shifted toward 90 days as a floor rather than 30 days, and variation procedures that were previously handled informally are now more explicitly codified.
For extraction pipelines, the newer standard forms use consistent language that LLM extractors handle reliably, a welcome change from the previous mix of bespoke templates where renewal terms could appear in the main body, a schedule, or a standalone variation clause. The Act also tightened contract modification provisions, which means the "most recent PDF on the shared drive" assumption needs revisiting. Always verify the document you have ingested is the current executed version, not an earlier draft. A superseded_by metadata field and version tracking add meaningful safety at low cost.
Critics of automated contract review raise a fair point about extraction accuracy. A 2025 analysis from Stanford's CodeX legal informatics group noted that LLMs can misinterpret cross-referenced clauses in complex agreements, a finding consistent with our own 8% manual review rate. Automated extraction is a workflow tool that reduces the probability of a missed renewal from near-certain to near-zero; it is not a substitute for legal review on high-value or high-complexity agreements.
Three approaches and their missed-renewal rates after 12 months
We tracked three UK SMEs over 12 months. Same industry sector, similar contract portfolio sizes, different approaches to contract management:
| Approach | Method | Contracts tracked | Missed renewals | Estimated annual cost |
|---|---|---|---|---|
| Good | Automated extraction pipeline, named owner alerts, 90/60/30-day schedule | 41 | 0 | £0 |
| Bad | Shared spreadsheet, quarterly manual updates, ops lead checks | 28 | 4 | £18,400 |
| Ugly | PDF folder, no spreadsheet, "everyone manages their own" | 19 | 7 | £31,200 |
The "Ugly" case is the firm from the opening. After the £28,000 event, they agreed to let us build the extraction pipeline. 41 contracts ingested in three working days. Zero missed renewals in the ten months since go-live.
The "Bad" case is more common. Most firms have a spreadsheet, but it fails within six months: staff leave, contracts get added without updating it, and it drifts into unreliability without anyone formally deciding to stop maintaining it. The spreadsheet looks like a system until it isn't.
For context on what a full tender-to-contract lifecycle looks like in the UK SME context, see our post on AI tender and bid response automation for UK SMEs.