You may have heard the term Loose Coupling in the SOA (Service Oriented Architecture) in software design or IaaS (Infrastructure as a Service) or PaaS (Platform as a Service) in the cloud automation topics. For me, it was a bit hard to catch at the beginning, but this simple explanation helped me better understand the actual meaning of Loose Coupling:
If your Apple IPOD’s battery dies, you need to replace the whole device as you can’t simply change the battery! That can be an example of a tightly coupled system which the health of your IPOD is tightly depended on the battery which is not replacable. An example of a loosely coupled in that aspect, I’m sure you can make a lot of examples.
When designing in the cloud (or any complex system) Loose Coupling plays an important role towards scalability and reliability of your applications which result in an easier automation. Loose Coupling is an approach against having a big complex (IT) system or applications; Instead design for smaller and simpler elements which can cooperate with each other to provide the same service.
In a loosely coupled system:
- Each component/element can scale independently if needed.
- Each can be modified separately.
- Failure in an element does not affect the rest of a system and
- Recovery from a failure is by far easier comparing a tightly coupled complex system.
All of these make a loosely coupled system to be more manageable, reliable and scalable and as a result, the operation’s tasks can be easily automated.
A very simple example of decoupling is when you remove a database service from an application server and deploy it on a dedicated server; The Same concept applies when you want to design your loosely coupled application, or decouple your existing complex system.
If you want to create a loosely coupled application you first need to make sure you Separate the Components, then define Standard Communication Interfaces for your elements; You may need to design an Automatic Service Discovery at each layer or design based on Asynchronous Integration method; Another aspect of a loosely coupled system is how Graceful is a Failure handled which leads to minimum/no effect to the rest of the system. These concepts are explained in this Amazon best practice document, And here is a summary:
Topics in this section:
Loosening as a Mindset
Whenever you built a component (can be a physical, virtual, or a piece of code ,.. ) stop for a moment and ask these questions?
- What happens if this element fails and what would be the effect on the service?
- Can I scale/change/recover this object without touching another part of the system?
Based on your answer to above questions, you need to rethink your design. Here are some strategies that can help you create a Loosely Coupled applications:
Build on top of a Standard Communication Interface
Instead of creating heavily customised connections between your components, create standard interfaces and APIs (like RESTful API) and make the communications through these interfaces; This way, you reduce/remove dependencies between your components as they are all communicating through your standard communication APIs; As they are less dependent to each other, failure in any part doesn’t prevent others from doing the normal operations.
One of the tools that can help you develop/build standard Interfaces is Amazon API Gateway. With this fully managed service, you can create APIs that can act as a “front door” for you applications to access their data and decouple them from the rest of the system.
Create a Built-in Service Discovery
When your components are decoupled and separated, they simply need a way to find and communication with each other. In this situation you have two option:
Hard code the communication information (e.g., the static IP address of the database server in the application server)
Develop an automatic service discovery built into your system
The latter is preferable as your sub-application can consume without prior knowledge about other components; as a result, you can add/remove without any service outage or required change.
One way you can achieve service discovery is through Amazon ELB (Elastic Load Balancer); With the unique DNS name of each load balancer you can assure a reliable service discovery from your application/web server whenever they want to consume another service (e.g, database). You can even add more abstraction layer by creating a DNS CNAME to decouple at load balancer from the DNS name.
Asynchronous Integration
If you have applications that don’t need an immediate response in the communication, you can decouple them from directly interacting each other by utilising and an intermediate storage layer (Like Amazon SQS). In this communication, normally one component generates events and another one consumes that event. So the source system sends the message to the external queuing system – instead of directly to the target application- and the target (consumer) consumed the message from the queue:

As you can see if any of the controllers fails other controllers can continue operating as per normal by putting/getting the message from the queues. you can also scale up/down each controller without affecting other layers.
Graceful Failure (Detect/Recovery)
A loosely coupled system can tolerate fault by gracefully recovery from failure. Here are some of the strategies to develop a graceful failure in your system:
- Amazon Route 53 DNS failover feature can monitor and detect a failed server and stop referring traffic to the failed component.
- You can utilise front-end caching systems which can redirect users to the cache content when the main wen site fails
- A failed task can be stored in a queue to be processed later when the system is healthy.