I claim that all (user) data in a database should be mutable by default. Always. Well, almost all data. There are only four exceptions.
1. The primary key
A dedicated column that serves as the unique identifier of the record (ideally, a
GUID or a consecutive number). Every table — without an exception, and I mean it — must have a separate column that uniquely identifies the record.
It may be tempting to use an existing column (such as
user table) as the primary key, but doing so makes it impossible to change a user’s email later on. Avoid this at all costs.
Instead, always use a separate column with a truly unique value and use this column exclusively to build relations and connect records in a database. That way, all other data (such as, for example,
slug) can always be changed without breaking anything.
2. Foreign keys
Similar to primary keys, foreign keys take care of connecting records and maintaining relationships in a database. These must be always treated as read-only, as they ensure data integrity.
3. Automatically generated values
Many databases use computed values such as timestamps (e.g.
created_at). All data that was generated without user input should generally be considered immutable. They usually provide meta information about a record and should be treated differently than user data.
4. Records that are immutable by their nature
Some database models include entirely read-only tables, where new data can be added, but existing data can never be modified. It can only be read. A common use case for this is a document activity log or a login history.
All other (user-entered) data should be mutable — always. It may sound obvious, but it’s not always the case. Of course, there can be exceptions, but 99% of the time, this should be the default.
Suppose I’m using a SaaS where I can create a workspace with my company’s name and slug. In case I ever rebrand from ”Average company” to ”Superior company”, I want to be able to change the name, the slug, the admin user’s email address, and so on. If this is not possible, it’s usually a sign of weak database design (or poor UX).
Thanks for reading. Feel free to follow me on Twitter.