Lars-Erik Kindblad
Writing about software development, architecture and security

Scaling Microservices Part 8 - Adjusting Service Boundaries

In the previous parts of our series on scaling microservices, we explored various techniques to enhance system performance. In this final article, we'll discuss how adjusting service boundaries can help reduce bottlenecks and complexity.

Defining service boundaries is one of the most important and challenging decisions in microservice architecture. These boundaries significantly influence daily development activities and are expensive to change later. While it's critical to carefully analyze and plan boundaries beforehand, it's equally important to adjust them as the system's landscape evolves.

When setting service boundaries, you must balance multiple needs and requirements. For example, if you have functionality A and B, how do you decide whether they should belong to the same service or be split into two?

1. Core Decision Principle: Loose Coupling and High Cohesion

In microservices, the goal is to achieve loose coupling and high cohesion:

  • Loose Coupling: Services should have minimal dependencies on each other. Changes in one service should not necessitate changes in another.
  • High Cohesion: Functionality within a service should be strongly related and interdependent.

If A and B have a strong dependency on each other, they might belong in the same service. On the other hand, if A and B are relatively independent, they should be separate services.

Diagram showing variations of coupling and cohesion

2. Deviations From the Core Decision Principle

Software architecture is the art of balancing often competing requirements and needs. While the core principle serves as an important guideline, we also need to consider a vast number of other factors:

  • Manageability: A single service should not be too large or complex for a team to manage effectively. If A and B are tightly coupled but too large for one team, splitting them into separate services might be necessary.
  • Business Ownership: If A and B have different business owners or funding sources, this may indicate they should be separate services.
  • Regulatory Requirements: If A and B are subject to different laws or regulations, separating them can simplify compliance.
  • Criticality: If one functionality is critical while the other is not, separating them may help reduce risks to critical operations.
  • Specialization: If one service requires highly specialized knowledge or skills, keeping it separate can improve focus and expertise.
  • Deployment and Release Cadence: If A and B have different deployment or release requirements, splitting them can enhance flexibility.
  • Security: If A requires a high level of security e.g. sensitive health data and B has higher exposure to vulnerabilities e.g. file uploads with transformations, they should be separate services to isolate risks.
  • Data Consistency: If A and B need strong data consistency, consider having them as a single service.
  • Performance:
    • Chattiness: If A and B generate significant network traffic between them, merging them into one service may improve performance.
    • Resource Intensity: If one functionality is highly resource-intensive, separating it into its own service can help distribute workloads and scale more effectively.

Conclusion

Adjusting service boundaries is not a one-time decision. As your system evolves, so do the needs of your architecture. Regularly revisiting and, when necessary, refining your service boundaries can help maintain a scalable, performant, and manageable system.

Remember, while these adjustments are costly, they can be invaluable in reducing complexity and bottlenecks in the long run. Properly defined boundaries lay the foundation for a successful microservices architecture that can adapt and scale with your organization's needs.