In a recent talk I gave for engineers at my employer, I explored principles of Lean Manufacturing and how they can be used to understand the communication patterns between microservices.
At a high level, every remote call can be seen as either a “push” or “pull”. In a manufacturing context, “pushing” follows a waterfall flow from inventory through multiple process to a stockpile of the ultimate product. This can be rigid and wasteful, if the inventory is not used, but is extremely convenient (i.e. fast) when there is an abundance of goods.By way of contrast a “pull” system allows the end-consumer to send a request signal that bubbles upwards through processes. This is very “lean” (very agile!) but has the potential to be quite slow if done incorrectly.
So if pushing : waterfall as pulling : agile, how can we think about the communication patterns afforded by various technologies?
In general, if there is an opportunity to build an index, you’re dealing with “push”.
If there is an opportunity for caching, you’re probably dealing with a “pull” design.
For example, any database table with an index needs to process every row (the inventory), before the benefits of the speed-up on read can be realized/enjoyed. These are systems that depend on “push”.
Similarly any time I read or GET a remote resource, using an API, there is generally an opportunity to cache the result and speed up future requests.
With this in mind we can begin to dissect various technologies.
Event-driven systems like Kafka are by definition “push”. One system produces messages and drops the mic. Possibly another system consumes the message, and does something with them. What’s important is that an inventory of messages is built up. There is no confirmation or guarantee of order. At worst we guarantee eventual consistency.
Search indexes and databases are by definition “push”, because before we can read (pull) from the index we need something written.
graphql is the quintessential “pull” system, affording clients the ability to say exactly the shape of they data they want. The challenge is whether we can satisfy their requirements fast enough.
If your system depends on any kind of transactional coordination between services, you’re likely living in the “push” world, where ordering and SLAs are requirements. This is the worst kind of microservice interdependence.
If your system can spew out messages without caring how or by whom they are used, you’re dealing with a push system in all its glory. Your microservices are more likely to be loosely coupled.
related ideas: