微服务共享领域层边界咨询:ERP多微服务架构问题探讨
Great question—this is one of the trickiest pitfalls teams face when scaling to microservices, especially if you’re coming from a monolithic DDD background where shared domain layers feel natural. Let’s break this down into two core parts: defining healthy shared boundaries, and unpacking the risks of your current shared domain layer approach.
How to Define Shared Item Boundaries
The key rule here is: only share what is truly universal, not what feels convenient. Here’s a practical framework to set boundaries:
Split "generic infrastructure" from "domain-specific logic"
- Safe to share: Purely technical, business-agnostic utilities (e.g.,
StringUtils, date/time helpers) or universal value objects (e.g.,EmailAddress,PhoneNumber—things with consistent validation rules across all contexts). - Never share: Domain entity abstractions (like your
CompanyorLocationinterfaces) unless you can guarantee every microservice uses them with identical business semantics. In most cases, HR’sCompany(focused on employee org structure) will have different needs than Orders’Company(focused on shipping/billing details).
- Safe to share: Purely technical, business-agnostic utilities (e.g.,
Follow the "minimum viable share" principle
- Ask: Does this shared code prevent duplicated work, or does it just create unnecessary coupling? If it’s the latter, skip sharing. For example, if two microservices both need a
Locationmodel but with different fields, let each define their own instead of forcing a one-size-fits-all shared interface.
- Ask: Does this shared code prevent duplicated work, or does it just create unnecessary coupling? If it’s the latter, skip sharing. For example, if two microservices both need a
Use contracts instead of code for cross-service communication
- Instead of sharing entity classes, define data schemas for APIs (via OpenAPI) or event streams (via Avro/Protobuf). Each microservice can then map these schemas to their own internal domain models, keeping evolution independent.
Assign clear ownership for shared components
- If you must maintain a shared library, designate a small team to own it. This prevents the "everyone uses it, no one fixes it" problem, and ensures changes are vetted for cross-service impact.
Risks of a Shared Domain Layer
Your current setup—sharing abstract entities like Company and Location across all microservices—can create long-term pain that undermines the core benefits of microservices:
Tight coupling kills independent evolution
- The biggest risk: A change to the shared
Companyinterface (e.g., adding anemployeeCountfield for HR) forces all microservices to update their dependency, even if Orders or Auth have no use for that field. This turns your "independent" microservices into a distributed monolith.
- The biggest risk: A change to the shared
Domain model atrophy
- Each microservice’s domain model should evolve to fit its specific business needs. A shared layer forces you to model entities around the lowest common denominator, leading to either incomplete models (missing fields needed by some services) or bloated models (carrying unused fields for others).
Version hell and dependency conflicts
- As microservices mature, they’ll have conflicting needs for the shared library. For example, Service A might need v1.0 (stable, no breaking changes) while Service B needs v2.0 (with new features). Managing these versions across deployments becomes a nightmare.
Debugging and traceability become harder
- When a bug occurs in a shared entity, you’ll have to check every microservice that uses it to narrow down the root cause. Cross-service dependencies turn simple issues into multi-team investigations.
Slower iteration speed
- Any change to the shared domain layer requires coordination with all affected teams, adding approval processes and delays. The fast, autonomous release cycles you wanted with microservices will grind to a halt.
Practical Next Steps for Your Team
Since you already have a shared domain layer, here’s how to course-correct gradually:
- Map domain semantics: Audit each microservice to document how it uses
Company,Location, etc. If there are meaningful differences (different fields, business rules), those are signs each service needs its own domain model. - Replace shared entities with contracts: Start with one microservice—replace its dependency on the shared layer with a local model that maps to your API/event schemas. Repeat this across services until the shared domain layer is no longer needed.
- Extract truly generic components: If some parts of the shared layer are universal (e.g., a
CountryCodevalue object), split those into a tiny, focused utility library—strictly no domain logic allowed.
内容的提问来源于stack exchange,提问作者user7492327

