Fallacies of distributed computing for Ruby developers

This morning I read Integrated systems for integrated programmers article by DHH. I totally agree with it, replacing a monolith by microservices won’t solve all its problems automagically. The same good practices and patterns applied correctly give benefits no matter what kind of application you develop.

On the other hand, especially in the era of microservices peak popularity, there is a group of problems that has a smaller impact on a single application than multiple ones communicating with each other.

Fallacies of distributed computing are a set of assertions made by people working at Sun Microsystems describing false assumptions that programmers new to distributed applications invariably make.

https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing

Microservices are distributed applications indeed. The fallacies should be carefully taken into consideration before making¬†Let’s split the monolith into microservices decision. It would be beneficial if each of us knew them and how to avoid their negative consequences in advance.

Let’s iterate over the assertions from Ruby developer point of view.

1.The network is reliable

How many times has your application raised an exception? Do you handle exceptions gracefully? What about less-known ones like Errno::ECONNREFUSED? The more services the more network communication is involved. The more your system depends on network communication, the more its reliability depends on the network.

Fortunately, there already are some good design pattern like the circuit breaker to limit consequences of network instability.

2. Latency is zero

Fetching records from a well-designed database hosted in the same region is usually extremely fast. What about an HTTP request between two microservices? Milliseconds are replaced by seconds frequently. Is such a response time acceptable? What when service B to prepare a response to a request received from service A needs to make another request to service C first? Response time may grow even more.

3. Bandwidth is infinite

There are a few main cloud providers today. A lot of network traffic travels between them. What if one of them will have a hiccup? Is your application ready for Net::ReadTimeout and Net:OpenTimeout exceptions? Have you set open and read timeout values for all external communication? Ruby gems like httparty and the Net:HTTP built-in class provides an easy way to do so.

4. The network is secure

As far as your microservices are hidden behind a virtual private network you are a bit safer. The more services are publicly available the higher chance to be attacked by malicious people or programs, though. Do you scan your gems for vulnerabilities on a regular basis? You can use bundler-audit and dependabot to avoid using vulnerable versions of libraries.

5. Topology doesn’t change

Network topology changes a lot. Every time a node (e.g. AWS EC2 instance) or Kubernetes pod is either created or removed a network looks different. Even though this fallacy is more about operations part of software delivery, there is at least one issue to be considered from developer point of view. How service A will behave when service B disappear aka there won’t be any instance of it for some reason? Do you have any fallback mechanism in place? You can test it by disabling service B on a pre-production environment and observing how service A behaves.

6. There is one administrator

The more services in a system the more people are involved in the maintenance of the system. The more people engaged the higher change to break something on different levels. When different teams develop microservices which communicate with each other more human communication is needed to make decisions. More protection mechanisms are needed to avoid breaking service A by introducing changes in service B, like contract tests.

7. Transport cost is zero

Similar to latency which does not equal zero, sending data from one point to another involves providing resources and infrastructure changes. Resources and the changes cost money. The more services involved the higher total cost.

8. The network is homogeneous

To address the nonhomogeneity of the network standards were created. HTTP, REST API and JSON became a standard set of tools for communication between microservices. It is important to keep the tools set unified across the system. Otherwise, you may end with a crazy combo of HTTP, SOAP, XML, JSON, AMQP, gRPC and other acronyms making the system much more complicated. Stay consistent.

Summary

Even though the eight fallacies were written down between 1994 and 1997 they may be new to you. I hope you will take them into consideration before creating a brand new application, no matter if it will be a microservice or a monolith. You can review your current applications as well to avoid unpleasant surprises in the future.

 

Igor Springer

I build web apps. From time to time I put my thoughts on paper. I hope that some of them will be valuable for you. To teach is to learn twice.