— 1 —
The domain layer is sacred.
The single largest source of architectural decay I've seen is the slow leak of framework concerns into the domain. A NestJS decorator here, a Drizzle import there, a Kafka envelope baked into a value object — each one looks like a small convenience at the time. A year later, the domain layer doesn't compile without the framework, can't be tested without booting the infrastructure, and can't be reasoned about without remembering which version of which adapter is in scope.
So I keep the domain pure. Pure TypeScript. No NestJS, no ORM, no broker, no provider SDK in the import graph. Aggregates, value objects, domain events, and repository interfaces — that's it. The application layer composes use-cases against those interfaces. The infrastructure layer implements them with whatever the world happens to be running this year.
The cost is more files, more interfaces, and the discipline to refuse the convenient import. The win is that every adapter — the database, the queue, the LLM provider, the search engine — becomes replaceable without touching the part of the code that encodes the business.