Welcome to this weekly blog! Every week, I publish articles on distributed systems, exploring fascinating concepts and their real-world applications.
There are two major problems in software development: Dependency Management and Information Hiding.
Microservices
Assume a server with multiple components. Over time, as more features are added, additional components will increase coupling and complexity. Recall the two problems in software: Dependency Management will become more complicated, and increased coupling will reduce abstraction. This single-server logic is called monolithic architecture.
Monolithic servers, if not well managed, tend to be rigid. A change in one module can break several others, leading to high maintenance costs. No developer wants to work on accumulated technical debt.
Microservices offer a solution to this. In a microservices architecture, multiple independent services handle specific functionalities. Each service encapsulates its own volatilities and is decoupled from others. They communicate through well-defined interfaces, such as APIs.
Decomposing services based on volatilities is a key system design skill but is beyond the scope of this article. We will discuss it in a future post.
In a microservices architecture, servers are now decoupled, and the dependency chain is broken. However, this approach also introduces some drawbacks:
Drawbacks of Microservices
Team Management: More workforce is required, as different teams may use different tech stacks and architectures. Microservices are costly in terms of workforce. If I were leading a company, I would never start with a microservices architecture. Instead, I would begin with a well-structured monolith with proper modularization. Over time, these modules could be separated and evolved into independent services.
Communication Complexity: In a microservices architecture, network calls or message queues are required for inter-service communication. This is neither faster nor simpler than direct module communication in a monolith.
Testing Challenges: Testing individual services is easy, but testing workflows involving multiple services can be complex.
Debugging and Operations: Managing and monitoring a distributed system is more expensive and complicated.
Data Consistency Issues: Since microservices operate in a distributed environment, maintaining consistency can be difficult, especially when services interact with shared data.
API Gateway
An API Gateway is a reverse proxy that serves as a single entry point for clients to interact with multiple backend services. It manages requests by routing, aggregating, and transforming them before reaching the appropriate service. API Gateways improve security, scalability, and performance by handling authentication, rate limiting, caching, and load balancing. They simplify client interactions by abstracting internal service complexities, allowing backend architectures to evolve without impacting external consumers.
API Gateways are particularly useful in microservices architectures.
Functionalities of an API Gateway
- Routing: An API Gateway exposes a public URL for clients, which is then routed to multiple underlying services.
Data Composition: In monolithic applications, data resides in a single store. In distributed systems, data is spread across multiple services, requiring data stitching. An API Gateway can compose responses from multiple services, but this introduces challenges such as reduced availability and potential data inconsistencies.
Protocol Translation: An API Gateway can translate between different inter-process communication (IPC) mechanisms, such as REST to gRPC, and expose different APIs for different clients. GraphQL, for example, enables flexible data querying, reducing the need for multiple APIs while optimizing responses for various use cases.
-
Authentication & Authorization: In microservices, authentication is best centralized at the API Gateway, while authorization should be handled by individual services to avoid domain logic coupling.
- Authentication verifies the client's identity.
- Authorization determines the client's permissions.
- In monolithic applications, authorization is often managed through roles assigned to session objects.
- In microservices, after authentication, the API Gateway issues a security token (e.g., JWT or opaque token), which internal services use for identity verification. JWTs are popular due to their self-contained nature.
- API keys are another common authentication method for public APIs.
Drawbacks of API Gateway
- Potential Development Bottlenecks: API Gateways can tightly couple with internal services, requiring updates when APIs change.
- Maintenance Overhead: API Gateways must scale with request rates, adding operational complexity.
- Latency: Since all requests pass through the API Gateway, additional processing time may be introduced.
Despite these drawbacks, API Gateways provide significant benefits in applications with many services.
An API Gateway can be implemented manually as a reverse proxy, or managed services like AWS API Gateway or Azure API Management can be used.
Conclusion
Microservices help solve monolithic architecture's rigidity and dependency issues but introduce new challenges, such as communication complexity and operational overhead. An API Gateway simplifies client interactions in a microservices environment but requires careful management to avoid bottlenecks. Choosing between monolithic and microservices architectures depends on the project's scale, team capabilities, and long-term goals.
Here are some links to my previous posts, which I publish every Sunday on distributed systems:
- Building Resilient Applications: Insights into Scalability and Distributed Systems
- Understanding Server Connections in Distributed Systems
- How are your connections with web secure and integral?
- Understanding System Models in Distributed Systems
Feel free to check them out and share your thoughts!
Top comments (0)