Shallow and deep merging give different answers
A shallow merge copies top-level keys from one document over another. If both documents have a `database` object, the second one replaces the first entirely - every nested key inside the original is lost, including keys the second document never mentioned. This is what JavaScript's object spread and `Object.assign` do, and it surprises people constantly.
A deep merge recurses. When both sides have an object at the same key, it merges those objects too, and keeps descending. Keys present in only one side survive. `{"db":{"host":"a","port":1}}` merged over `{"db":{"host":"b"}}` yields `{"db":{"host":"b","port":1}}` - the port survives, which is almost always what you wanted.
For layered configuration, deep merging is essentially always the correct choice. A production override that specifies only `database.host` should not silently discard the pool size, timeout and credentials that the base layer defined.