In my opinion this depends on the use case. If one service has a strong dependency to a different service, it may be a case of "distributed monolith" and they should consider if the functionality should be moved to the original service instead.
If two services need to communicate with each other, I don't see how a message queue makes the coupling less robust. What is the difference between sending a message or making a http call? You still have a coupling between the two services.
Message queues used right can actually increase operational robustness in my opinion. By placing a message on a queue you get a lot of functionality for free.
- You distribute the load automatically so that the risk of overloading a single instance is reduced
- You can limit the ingestion flow, so that services only process the data at a rate that they can handle - If a service fails or shuts down, the message remains on the queue for the next instance to retry. You get a lot of retry logic for "free".
- You can easily monitor and scale resources based on the processing rate of the queue itself. Some queues can be allowed to grow large during peek hours, because they can be processed during off hours, while others may require scaling up the service capacity to cover a minimum latency requirement.
Misuse of message queues may of course lead to distributed monoliths and add a lot of complexity in understanding how data flows within the system. This is not something specific for queues and it's the same for direct HTTP calls. As all things, we need to use the right tool for the right purpose.
Actually, one of my pet peeves are internal web hooks. Web hooks are good at notifying an external partner compared to the alternatives, but the complexity is too great to justify its use for internal services as well. Just use a message queue instead for your own services.
And it is essentially your point.
[1] https://news.ycombinator.com/item?id=38944611 -- https://newsletter.pragmaticengineer.com/p/dead-code-getting...
I have to caveat this though:
> Therefore, reducing coupling will reduce the cost of change.
This seems like unwise advice. People are going to read it as "coupling = bad" and then try to eliminate coupling even between components that are still coupled, through things like dynamic typing, queues and so on. This only reduces the appearance of coupling.
For example say you have an API endpoint that is supposed to perform some action in another service. A lot of people would "decouple" them by having the endpoint place a request in some shared Kafka/MQTT queue or a file or whatever, and then the other service can poll that. Tada! Decoupled! Much better than a direct RPC call right?
Except they still depend on each other - you've just made the coupling less robust, so it can easily break when you make a mistake refactoring.