Skip to content

Part 2 of 7 · Tax rate updater series ~5 min read

How the rate register works

This post has almost no engineering in it, which is honest, because the register is the part of this system that no amount of code will build for you. It is an afternoon of asking people where numbers live, and it is worth an afternoon regardless of whether you build anything else in this series.

Key takeaways

  • A register row is a rate, a source, an effective date, an owner, and a list of places.
  • The list of places is the only part software cannot supply. Everything else is lookup.
  • Four reliable ways to find rates nobody remembers, in rough order of yield.
  • A rate you cannot find an official source for is still worth registering, marked as manual.
  • The register lives in a sheet, so it survives the system being switched off.

One row

rate            Standard VAT rate
value           0.20
format          percent | amount | threshold
source_url      https://... the official publication
source_kind     html | pdf | feed | manual
selector        the part of the page the value lives in
effective_from  2011-01-04
used_in         quoting sheet (tab Prices, B4)
                price list PDF (page 2)
                invoice template (Xero, tax rate ’Standard’)
                booking form (config: VAT_RATE)
owner           finance@example.com
last_checked    2026-07-15T06:00:00Z
last_seen_value 0.20

The used_in entries are deliberately specific — a tab and a cell, a page number, a named setting, a config key. “The quoting spreadsheet” is not actionable at eight in the morning eleven months from now; “quoting sheet, tab Prices, cell B4” is.

Finding the rates nobody remembers

Four ways to find the tax rates a business has written downA vertical chain of five steps entered by a box labelled Start empty, because nobody has this list. Step one searches your own files across Drive, S3 and code repositories for percent signs and rate words. Step two reads last year's tax returns for every rate you filed. Step three asks the three people who make quotes, invoices and prices. Step four checks every template: invoice, quote and contract. Step five is A register, usually eight to twenty rows. A note says the third step finds the ones the first two cannot, because rates live in people.AWS ACCOUNTStart emptynobody has this listSearch your own filesfor % signs and rate wordsDrive, S3, reposeverything you ownRead last year's returnsevery rate you filedAsk the three peoplewho make quotes,invoices and pricesCheck every templateinvoice, quote, contractA registerusually 8-20 rowsThe third step finds the ones the first two cannot. Rates live in people.
Fig 1. Four ways to build the register, in rough order of yield. The third is the one that finds the rates that exist only as a habit.
  • Storage
  • Machine learning
  • Analytics
  • Front-end & mobile
  • People
  • Search your own files. A grep across Drive, shared folders and any code for percent signs next to words like tax, VAT, duty, rate and threshold finds a surprising amount in twenty minutes. It finds the written-down ones.
  • Read last year’s returns. Every rate you actually filed against is on a form somewhere, and the accountant’s working papers usually name the thresholds too. This finds the ones you use correctly but never wrote down.
  • Ask three people. Whoever prices work, whoever raises invoices, and whoever deals with the accountant. The question is not “what rates do we use” — nobody can answer that — it is “when you quote a job, where do you get the tax number from?” The answers are frequently “I know it” and that is a register row.
  • Check every template. Invoice, quote, contract, order form, rate card. Numbers get typed into templates once and inherited forever.

Rates with no official source

Some numbers you rely on are not published anywhere machine-readable: a rate agreed with your accountant, a threshold in a trade body’s guidance, a duty rate that only appears in a PDF schedule. Those still belong in the register, marked manual.

A manual row is never watched, but it is reviewed — the system sends a reminder on a cadence you set, usually annually before the fiscal year, saying “these six rates are not watched; please confirm they are still right”. That is a much weaker control than watching, and it is enormously better than the rate not being on any list at all.

Keeping the register in a sheet

The register lives in a spreadsheet, read by the system rather than owned by it. That is a deliberate constraint and it costs nothing: a sheet can be edited by a bookkeeper, survives the system being switched off, can be printed and handed to an accountant, and requires no permissions model.

What a good register row avoids

  • Vagueness in used_in. “The website” is not a place; “the pricing page, second paragraph” is.
  • A source that is a summary rather than a publication. Aggregator sites are convenient, occasionally wrong, and unusable as an audit trail.
  • One row for two rates. A reduced rate and a standard rate are separate rows with separate effective dates, even when they are published on the same page.
  • An owner who is a team. “Finance” does not read email; a person does.

Next: how the watcher reads a source without producing a false alarm every time a website is redesigned.

All posts