The Service Scorecard
The Service Scorecard is a tool for teams to help them determine what belongs in a new service and whether it is a net benefit. See a more robust description below. A higher score is better for a candidate service. Scores can range from -6 to at least 6 if it's doing everything correctly.
Service Total 0
This service would probably be too tightly coupled to have any real benefit.
The advantages of splitting out services are evangelized constantly to developers and managers. And why not? Who doesn't love separation of concerns, faster iteration, as well as independent scaling and SLAs. However, designing the boundaries of those services is a hard problem and it can go poorly. How poorly? You can easily end up with something much worse than an unruly monolith.
When your functions share space in memory, it's much easier to have tightly coupled interfaces. For example, you may have a rich context object that gets passed down through a series of methods. Small changes to that context object require changes to a whole swath of unrelated functions down the chain. This kind of thing slows down development.
Creating a service and placing certain functions in it encourages you to think about the interface and the boundaries of responsibility. Yet it makes no guarantees. It's bad enough if you are passing around rich context objects between entirely separate functions. When you do this kind of thing with services, you are forcing situations like coordinated deployments. You now have slower iteration than with a monolith.
This scorecard contains a series of reflective questions designed to get teams to think about what a new service will consist of and whether or not it's a net positive for the application.
Number of Clients
For every client > 1, +2 points.
Every service adds overhead to a project. The biggest impact in offsetting that overhead depends on the number of distinct clients that can make use of it. If you only have one client, you really just have one service that happens to be separated by a network interface. Cleanly separated function calls and good error handling will provide almost all the same benefits without the context switching, secrets management, etc. that goes with splitting out a new service.
On the other hand, for every client service after the first, you're getting a greater return on investment. Each client represents functionality that doesn't have to be copied, consistency across your application, and you have clear ownership over a problem domain.
If yes, -1
Intimate knowledge about clients' data types indicates there will be tightly coupled business logic between the services. When services are tightly coupled, it means that changes are more likely to require coordination. It also implies that your service has a leaky abstraction where the boundary between what one service is responsible for versus another is fluid.
Unique Client Behaviors
If yes, -1
Client specific behaviors are another example of a service internalizing the business logic of other application components. It's likely that down the road this will require coordinated deployments when the behavior needs to change. Additionally, this approach doesn't scale. You can avoid this if the behavior can be parameterized as an option to a function call.
Responsibility & Ownership
If Yes, +2
Assigning ownership to a service will result in a better service over time. When a team is responsible for a service, it is more likely to be kept up to date. It is less likely to have security flaws. When triage is necessary, it should take less time to solve.
Third Party Offerings
If yes, -2
The best candidates for separate services are commmonly offered as SaaS platforms. This is because they are agnostic to most business logic. Building your own service when a third party is a viable option will likely result in a worse result that costs more engineering time and money. Some times third party services are not an option due to privacy, security, or compliance concerns. In this case, consider your response a "No".
Downtime & Distinct SLAs
If yes, +2. If no, -2
One of the largest benefits of network separated services that each service warrants a different SLA. If your entire application stops functioning when this service goes down, you simply have a network separated monolith. Authentication services ride a fine line here. They typically require the highest SLAs and if users cannot log in then most other features are often unavailable. Often shared authentication is a necessity, so use your judgement.
On the other hand, a service that has minimal impact on uptime for the application as a whole is a great candidate. It can be thought of as a pluggable asset that can be manipulated as necessary.