"long lived mutable structures tend to drift into unexpected states"
Why are those "tend to drift" ? As an example I wrote sort of like game server for one of my applications. Internally it has those exact forever lived mutable structures. I've never observed it to drift into any unpredictable state. Works like a charm and running for many month. I only reboot it when I need to update it to a new version.
The only catch here is that all data fit into RAM. With the amount of RAM modern computers can be stuffed with I do not really see if my server would ever run out of it.
Of course it backed up by database but it merely serves as a persistence layer for this particular application.
Consider why 3rd normal form exists to begin with.
In the real world, let's say you have a shipping address and a billing address for a customer, and they are usually (but not always) the same.
Eventually, a customer moves, changing both of their addresses. But the user forgets to change their billing address with their delivery address.
A proper database would have a 'billing address is same as delivery address' logic, following the principle of DRY (don't repeat yourself).
----------
There are lots of examples here of what can go wrong when you repeat yourself in a database application. The user may have an error when repeating themselves over the dataset (delivery address is correct, but zip code on billing address has a typo).
Dealing with these issues at scale, with hundreds of thousands of customers, is certainly a problem. Normal forms can formalize these issues and help the business owner avoid the problems.
Where do you verify the existence of zip codes and cities? Where do you check for typos? How do you prevent contradictions on the submitted information?
Your human customers will make many mistakes. Your logic must hold up even in the presence of faulty data.
"A proper database would have a 'billing address is same as delivery address logic"
The database does not have logic like this. It has to be implemented by stored procedure. When I have application server all such logic (if applicable) is handled by code in much more performant way. No data goes to a database directly. Everything passes through the app server along with the validation data transformation etc, etc. As already said the database in this particular case is nothing more but persistence layer.
Again we can put all kind of theoretical speculations but as I already said, my particular server does not have data drifting to some faulty states.
>> "A proper database would have a 'billing address is same as delivery address logic"
> The database does not have logic like this.
Of course it wouldn't have 'logic', databases are just stores of data.
You'd have one 'address' table, with probably a int-primary/surrogate key. Then the 'delivery' and 'billing' address would be an int, pointing to the address table.
Furthermore, the billing and delivery address would be foreign keys, so the internal database logic would keep the tables in sync with no application code required.
With the data organized in this manner, the application code becomes logic free and braindead easy to write. Or at least, corner cases become easier to handle and more explicit. (Say two customers share the same address, do you allow repeats in the address table? Or do you allow customers to tie address information together? Either way, your decision rests on how you define the primary key)
> When I have application server all such logic (if applicable) is handled by code in much more performant way.
The most performant way is no logic at all. A proper database removes a lot of checks, the storage format itself naturally creates logic free code.
Some application logic is necessary of course. But you can minimize the logic needed by thinking about data layout.
Why are those "tend to drift" ? As an example I wrote sort of like game server for one of my applications. Internally it has those exact forever lived mutable structures. I've never observed it to drift into any unpredictable state. Works like a charm and running for many month. I only reboot it when I need to update it to a new version.
The only catch here is that all data fit into RAM. With the amount of RAM modern computers can be stuffed with I do not really see if my server would ever run out of it.
Of course it backed up by database but it merely serves as a persistence layer for this particular application.