Draft preview. Not in the index, feed or sitemap.

Why your business software needs an audit trail, and what it should record

An audit trail records every change to your business data: who made it, what changed, when, from what and why. The useful kind can't be edited, even by your own administrators or your supplier. Corrections go in as new entries, totals are worked out from the entries, and the database itself refuses edits and deletes, so a missing item or an unexplained change points at a person, a place and a time.

By The Spiral team Published 11 min read

Audit trail: the short answer

An audit trail is a record of every change to your business data: who made it, what changed, when, from what, and why. Your software needs one from the day more than one person can change a price, a stock count or an invoice. The useful kind can't be edited, even by your own administrators or your supplier. Corrections go in as new entries, so the mistake and the fix both stay on the record.

The weaker kind is a log written beside records that anyone with enough access can still change. The Post Office's Horizon system had that weakness. In 2019 the High Court found that its supplier could alter a branch's accounts without the subpostmaster knowing.

This guide is for owners and operations leads at UK and EU firms of 10 to 200 people. You may be commissioning internal software or a web application, or living with one that can't answer "who changed this?". Our internal software page lists an audit trail among the things we build. Here is what it should record, how to stop anyone quietly editing the past, and how to check it before you accept the software.

What an audit trail should record

Each entry answers the same few questions. Leave one out and the trail stops settling arguments.

FieldExampleWhy it matters
WhoAna, depot 1; "invoice matcher (automation)"; a named engineer at your supplierA change nobody can attribute is a change nobody can explain
WhatTwo floor sanders moved from depot 1 to van 3The event itself, in the business's own words
Before and afterStatus changed from "on hire" to "returned"Shows what the record said when someone relied on it
WhenThe server's time, with the time zoneA phone's clock can be wrong or changed
WhyA reason from a short list, plus a noteThe question everyone asks a month later
Where fromAdmin screen, phone app, import, API, database consoleShows changes that went around the normal screens
CorrectsA link to the entry it reverses, if anyKeeps the mistake and the fix together

Make the reason a required field with a short list of values. An optional free-text box is usually empty on the day you need it. A required field is either filled in or missing, and the software can refuse to save without it.

Record the person who acted, not whoever happens to be logged in. Shared tablets and phones with poor signal make this harder than it sounds. A change saved offline and sent an hour later must keep its real author, which our guide to offline-first apps covers.

Give every automation and AI agent its own name in the trail, never the name of the person who set it up. Our agent building page promises logs of what an agent did and why. Those logs belong in the same trail as your staff's changes, so one screen tells a record's whole story.

Two ways to build an audit trail

The first kind is easier to build, and weaker. It keeps each record as a current value that people edit, and writes a line to a log whenever the application changes it.

The log is only as complete as the code that writes it. A bulk import that skips the logging leaves no line. Neither does a support engineer fixing data in the database console, or a script your supplier runs at night.

The second kind stores what happened and works out the current state from it. Nobody types a stock count; people record movements, and the count is the sum of the movements. Nobody edits an invoice total; they issue a credit note. The history is the record itself, so there's nothing beside it to fall out of step.

Edit the record, log the changeRecord events, work out the state
What's storedThe current value, plus a separate logEvery event; totals are sums of events
A change made outside the appChanges the record; the log may miss itRefused by the database
A correctionOverwrites the old valueA new entry that points at the mistake
A stock count that's wrongSomeone edits it to match the shelf, and the loss disappearsThe gap between the entries and the shelf stays visible
Adding it laterStraightforwardHard, so decide before the build
SuitsSettings, drafts, web page contentMoney, stock, access rights, promises to customers

OWASP, a non-profit security foundation, recommends the second approach in its Top 10 for 2025, a list of the most critical web application security risks. It advises an audit trail for all transactions, with integrity controls against tampering or deletion, such as append-only database tables. Append-only means rows can be added, but never changed or removed.

A worked example: three missing floor sanders

Say you run a 30-person tool and equipment hire firm with two depots. The system says depot 1 holds 14 floor sanders. The shelf holds 11.

In software of the first kind, someone at the depot edits the count to 11 and types "stock check". The number is now right, and the loss has left the record. When it happens again next quarter, nobody can say whether it's theft, a booking error or a van that was never unloaded.

In software of the second kind, nobody can edit the count. Every sander that left or arrived has its own entry: hired out, returned, moved between depots, sent for repair. Walk through the entries and three missing machines become three questions with names and dates.

Two went out on one hire on a Tuesday, and only one came back. The third left for depot 2, which never recorded it arriving. Closing the gap is an entry too: a write-off, with a reason and a manager's approval, pointing at the movements it explains. The count matches the shelf, and the history still shows why.

Wherever money or stock moves, this is the design we recommend, because it turns "we come up short sometimes" into a short list of movements to check. It holds up better when the depot staff who record movements can't see what each machine is worth, so nobody can pick out which entries would be safe to fake. Keeping "what you may change" apart from "what you may see" is the subject of our guide to user roles and permissions.

Corrections go in as new entries

Mistakes still happen, so the trail has to allow for them. The rule: never change or remove an entry; add one that reverses it and points back.

So a wrongly keyed invoice gets a credit note, and a movement recorded twice gets a reversing movement. Delete becomes archive: a customer removed by mistake is archived and then restored, and both steps show.

Bookkeeping already works this way, and some countries write it into law. Germany's Commercial Code says an entry may not be changed so that its original content can no longer be established. Nor may a change leave it unclear whether it was made at the time or later (section 239, official English translation). In the UK, section 386 of the Companies Act 2006 requires accounting records that show and explain the company's transactions.

Billing is where most firms meet this first, with failed cards, downgrades and refunds, which our guide to SaaS billing beyond the happy path covers. Risky actions in your admin need the same care, and our admin dashboard guide shows what a bank's payment screen got wrong.

The people with the most access must appear in the trail

The Post Office's Horizon system shows what happens when they don't. Horizon ran the accounts in Post Office branches from 2000. In 2019 the High Court ruled on a set of technical questions about it in Bates v Post Office (No 6).

Mr Justice Fraser found that Fujitsu, which ran Horizon, could insert, edit or delete transactions in a branch's accounts without the subpostmaster knowing or agreeing. A transaction inserted at the counter could appear under the user ID of whoever was logged on there. A Fujitsu witness accepted that it would look as though the subpostmaster had done it.

The records of what Fujitsu's staff did with that access were thin. Their logs didn't exist before 2009, the court found, and until July 2015 showed only when someone logged on and off. The judgment records that one support role was used 2,175 times between 2009 and 2019, about once a working day, with very little detail on what for.

Both sides' IT experts agreed on the standard Horizon missed. Some technical staff will always need deep access to the database. Keep that group small, they said, with "each action that they take whilst logged in to be recorded and audited". The judge called this entirely conventional.

Subpostmasters, meanwhile, couldn't even record a dispute: Horizon had no dispute button, by design. Parliament later passed the Post Office (Horizon System) Offences Act 2024 to quash convictions for offences alleged while Horizon was in use.

The lessons carry over to much smaller systems.

  • Your supplier's engineers, your IT contractor and your own administrators appear in the trail under their own names, like everyone else.
  • Their changes to live data go through the same recorded path as any other change, never around it.
  • The people a record concerns can read its history and flag an entry they disagree with.

Enforce it in the database, not only in the application

A rule in the application's code protects you from the application. It doesn't protect you from an import, a script or an engineer with database access. Put the rule where every route passes, which is the database.

  1. Give the account your application uses permission to add rows to the history tables, but not to change or remove them. In PostgreSQL, a widely used database, that's one REVOKE command. A database trigger can refuse edits and deletes from other accounts as well.
  2. Let the database check the rules that must always hold, such as a stock level that can never go below zero.
  3. Send a copy of the trail somewhere the application can't overwrite. Amazon S3's Object Lock is one example: it stores files on a write-once basis, locked against deletion for a period you set.
  4. Include the trail in your backups. Now and then, restore one to a test copy and check the history came back.

Someone with full control of the database can still switch the first two off. That's why the copy and the backups exist, and why very few people should hold that level of access, each named in the trail.

Audit trails and personal data

An append-only trail and the right to erasure look as if they clash. They rarely do, if you design for both from the start.

  • Store a reference to a person, such as a customer number, rather than copying their name and address into every entry. Erasing or anonymising the customer record then removes most personal detail without rewriting history.
  • Keep secrets out entirely. OWASP's logging cheat sheet lists passwords, session tokens, card data and encryption keys among the data to mask or leave out.
  • The ICO, the UK's data protection regulator, says the right to erasure doesn't apply where you need the data to comply with a legal obligation. UK companies must keep accounting records for six years from the end of the financial year they relate to, so an invoice's history stays.
  • Set a retention period for each kind of entry, and delete entries on a schedule when it runs out. That scheduled job is the one deletion the design allows, and it records that it ran and how much it removed.

Retention periods vary by sector and country, so agree yours with your accountant or legal adviser before the build.

When you don't need to build one

Often you don't. Build the full design only where the records justify it.

  • If the records live in an accounting or sales product, use its history. QuickBooks Online keeps an audit log of sign-ins, settings changes and edits, and Intuit says its events stay available for two years. Xero keeps a history and notes on invoices, contacts, payments and other records. Check what yours records and how far back it goes.
  • Not every table needs the event design. Settings, drafts and web page content can be edited in place with a simple change log.
  • If one person keeps a list in a spreadsheet and nobody else relies on it, a trail adds little. Once several people edit it and the business depends on it, it has probably outgrown the file, which our guide to replacing spreadsheets with software covers.

How to check an audit trail before you accept the software

Ask the builder to show you each check on a test copy with realistic data.

  1. Change a price, then find who changed it, from what, to what, when and why, in the admin screens rather than a database console.
  2. Try to delete an invoice. It should be voided or credited with a reason, and the original should stay visible beside the correction.
  3. Save a change without a reason. The software should refuse.
  4. Ask who at the supplier can change live data directly, and where those changes appear. The right answer is "in the same trail, under their own names".
  5. Ask the builder to edit a history row using the application's own database account. The database should refuse.
  6. Restore last night's backup to a test copy and check the history came back with it.
  7. Ask how long each kind of entry is kept, and what deletes it when that time is up.

When we build, the code, the hosting and the documentation sit in your company's own accounts, so the trail is yours as well. A future developer can read it without asking us.

Start with the records people argue about

This week, list the records that cause arguments, go missing or get fixed by hand: stock counts, prices, discounts, timesheets, refunds. Beside each one, note the last time someone asked "who changed this?" and whether anyone could answer.

That list is where your audit trail starts. Give it to whoever builds your software, and ask how each record's history will be stored, who can change it, and who can read it.

Questions

Can we add an audit trail to software we already have?

Usually, in stages. A database trigger can record every change to your most important tables from today, whether it comes from a screen, an import or a script. The history before that day is gone, so start soon with the records that move money or stock. Moving a record from 'edit the value' to 'record the events' is a bigger job, because every screen, import and report that writes the value directly has to change too.

Does an audit trail slow the software down?

Not in a way most firms notice. Each change adds a row, which is routine work for a database. What grows over the years is storage. Plan where old entries go and when they are deleted, and index the trail by record and date so the history screen stays quick.

Is version history in Microsoft 365 or Google Sheets an audit trail?

Partly. It shows that a file or cell changed and who changed it. It doesn't ask anyone for a reason, and by default anyone who can edit one cell can edit them all. That suits a file one team works on. For records the business depends on, such as stock, prices or refunds, it's a sign to move them into software.

How we wrote this: drafted with AI, then checked and edited by the people who build our projects. Figures come from our own work or from the linked sources.

Tell us what is slow

Describe the project, or the part of the business that still runs by hand. You will hear back within one business day, from the people who would build it.

info@thespiral.studio