No matter how well a system is designed, there will be days when someone has to change data by hand: correcting a mistyped address, moving an order back to a previous status, fixing a value a bug wrote. These edits are legitimate. The trouble starts when nobody can say who changed what, when, and why.
What goes wrong without a record
- A report suddenly disagrees with last week's and nobody knows whether the data or the report changed.
- A customer disputes a figure and the team cannot show how it got there.
- An auditor asks for evidence of control over production changes and the only answer is "we trust our people".
- A mistaken bulk update cannot be reversed because the old values were never saved.
What a useful audit entry contains
The goal is to answer four questions without guessing: who, when, what, and what it used to be.
- Who: the signed-in user, not a shared database account.
- When: a server-side timestamp the user cannot set.
- What: the table and the row key that were touched, and the type of change (insert, update, delete, or a schema change).
- Before and after: the old value and the new value of each changed column.
- Which request: an identifier that groups all rows changed by one action, so a 500-row update reads as one event rather than 500 unrelated lines.
It has to be tamper-resistant
An audit log that the people being audited can edit or delete is worthless. Write it from the server side only, never from the browser, keep it separate from the data it describes, and limit who can read it to people with the right role. A log that can be quietly rewritten gives false confidence, which is worse than no log.
Keep it searchable
A log nobody can search will not be used. You should be able to filter by user, table, type of change and time range, and to export a slice to CSV for a reviewer or for a ticket. Retention matters as well: decide how long you need to answer questions, often a quarter for operations and longer for finance.
Beyond data edits
Row changes are only part of the story. Schema changes (adding or dropping a column), pipeline edits, and permission changes such as adding a member or promoting someone to admin should be recorded in the same place. Many incidents trace back to a permission or a schema change, not to a single data row.
A small checklist
- Every person has their own login; no shared credentials.
- The log is written by the server, not editable from the interface.
- Entries show old and new values.
- You can filter and export it.
- Someone reviews it on a schedule, not only after an incident.
In Ruamhub
Ruamhub records every data edit, table structure change, pipeline change and member permission change automatically. Entries carry the before and after values, can be filtered by category and time range, and can be exported to CSV. How long entries are kept depends on your plan.