Should microservices share technologies and platform capabilities?
Should agile teams be encouraged to share technologies when they are developing microservices?
A team-centric, polyglot view suggests that teams should be free to choose the most appropriate technology for the task at hand. Development stacks, data persistence and operational tooling all become something for each individual team to decide. This freedom can help individual teams to become more autonomous, reducing dependencies and accelerating development.
This may work for smaller organisations but it can bring significant overheads at scale. It can make sense for larger enterprises to provide a set of shared technologies and platform services that every team can use. This typically includes areas such as hardware, source code control, deployment automation, data persistence, messaging and authentication.
The rationale is to narrow the choices available to teams in order to manage complexity and reduce costs. For example, it may not be practical for each team to build and maintain their own resilient database infrastructure complete with appropriate replication, failover and disaster recovery. This does not mean that teams will share data, but they will share the same set of servers, typically under the management of a separate infrastructure team.
This notion of shared capability does make it easier to manage change safely. Deployments become more predictable and the effects of changing scale are easier to understand. In this sense, shared capabilities can support greater agility by reducing the complexity and risk involved in delivery.
The threat to team autonomy
Shared capabilities can run counter to the agile notion that a confident and empowered team should be able to choose its own weapons. Some organisations prefer to give their teams a greater degree of autonomy and some teams insist on it. This is particularly the case when speed of delivery is paramount.
There can be tension between the team sovereignty promised by agile and the needs of an organisation that is seeking to achieve economies of scale. Scaled agile frameworks such as SAFe and LeSS exasperate this by adding layers of formal governance on top of the basic units of agile teams. These teams find they have product managers telling them what to build, A PMO telling them what to report on, an enterprise architect telling them what technologies to adopt and infrastructure teams telling them which servers to use.
Even with the very most decentralized and autonomous organisations there is still a need for some degree of shared infrastructure. Spotify may emphasise the autonomy of their teams, but they have a shared operations team to facilitate more efficient code production, a matrix organisation to manage cross-team collaboration and an architecture team to look after a longer-term technology roadmap.
If services need to collaborate at all then some degree of shared capabilities are inevitable, particularly at scale where the demands of running a scalable infrastructure may be too large for any single team to manage. At the very least there needs to be some agreement around the “rules of the road” in terms of the protocols used which in turn can give rise to some shared infrastructure such as message brokers or API gateways.
Local services and capabilities
Although there may always be some degree of shared infrastructure, there will be some capabilities that teams always manage locally.
Forcing everybody to use the same development tools and frameworks does not necessarily scale all that well. The effort required in getting everybody to use the same logging library or IOC container is unlikely to attract any meaningful return on investment. Besides, if a team is going to take responsibility for the results then it should be able to make some of the decisions around how they were produced.
The trick is to know when to let teams do their own thing. Local capabilities are those that a single team can manage wholly and completely under their own steam. Managing a robust database infrastructure will be beyond the capabilities of most teams, though they should be able to decide on the most appropriate development tools or runtime configuration.
The exact division between local and shared services is one that reflects the organisation's culture as much as anything. The more federated and distributed an organisation's structure, the less likely it is to have a large number of shared services. An organisation that favours delivery speed over all else is more likely to view any shared infrastructure as “red tape” that should be removed.
A pragmatic approach to dependencies
Some microservice approaches advocate embedding every dependency within a service, preferably through some form of container technology. This enables service deployment anytime and anywhere without any coordination with the rest of the system.
This strict approach to dependency embedding may look good on paper, but it is both impractical and wasteful for all but the simplest of use cases. You will have a very hard time embedding any large-scale data persistence technology in every service. Ideally, there are “heavy assets” which should be made available in a usable and discoverable for in any place where a service might be deployed.
Services don not share data in this more pragmatic approach, but they do share infrastructure. This provides a middle ground where the data and context are separate but an organisation can still enjoy the economies of scale that a shared infrastructure can bring.