The problem is that different contexts have different escaping rules. It’s not possible to give a one-size-fits-all answer from the server side. It has to be done in a context-aware way.
Field A is plain text. Someone enters the value “Alpha & Beta”. Now, what does your server do? If it sanitises by stripping HTML characters, you’ve just blocked valid input; not good. If it doesn’t sanitise but instead unconditionally escapes HTML, somewhere, sooner or later, you’re going to end up with an “Alpha & Beta” shown to the user, when the value gets used in a place that isn’t taking serialised HTML. It always happens sooner or later. (If it doesn’t sanitise or escape, and the client doesn’t escape but just drops it directly into the serialised HTML, that’s an injection vulnerability.)
Field B is HTML. Someone enters the value “<img src=/ onerror=alert('pwnd')>”. Now, what does your server do? If it sanitises by applying a tag/attribute whitelist so that you end up with perhaps “<img src="/">”, fine.
The old tried and true strategy of "never sanitize data, push to the database with prepared statements and escape in the templates" is basically bulletproof.
It’s not an unnecessary complication. You fundamentally need to know what format you’re embedding something into, in order to encode it, and the server can’t know that.
Depending on what you do, you may want it unencoded, encoded for HTML data or double-quoted attribute value state (& → &, < → <, " → "), encoded for a URL query string parameter value (percent-encoding but with & → %26 as well), and there are several more reasonable possibilities even in the browser frontend context.
These encodings are incompatible, therefore it’s impossible for the server to just choose one and have it work everywhere.
Server-side sanitization and xss injection should be left in the 2000s php era.
If you mean filtering out undesirable parts of a document (e.g. disallowing <script> element or onclick attribute), that should normally be done on the server, before storage.
If instead you mean serialising, writing a value into a serialised document: then this should be done at the point you’re creating the serialised document. (That is, where you’re emitting the HTML.)
But the golden standard is not to generate serialised HTML manually, but to generate a DOM tree, and serialise that (though sadly it’s still a tad fraught because HTML syntax is such a mess; it works better in XML syntax).
This final point may be easier to describe by comparison to JSON: do you emit a JSON response by writing `{`, then writing `"some_key":`, then writing `[`, then writing `"\"hello\""` after carefully escaping the quotation marks, and so on? You can, but in practice it’s very rarely done. Rather, you create a JSON document, and then serialise it, e.g. with JSON.stringify inside a browser. In like manner, if you construct a proper DOM tree, you don’t need to worry about things like escaping.