In an ever-expanding digital world, building top-tier backend systems becomes more important to properly back numerous frontend facing applications. A stumbling backend, or engine as with Formule 1, seriously obstructs digital acceleration and impacts overall user experience. That’s why we focus on building performant backend systems aiming for resiliency, security, and scalability, capable of growing together with you and your clients’ needs.
Here we zoom in on 3 technical advantages of using our API Gateway approach as described in our previous blog post.
A main advantage of using our API gateway approach is that you can move logic from the different application servers to your central gateway, minimizing repetitive work and streamlining development of common features.
For example, authentication: in a traditional approach, each client develops its separate authentication logic that is used to support proper authorization against different backend services. But when the volume of backend services increases, it becomes clear that the development and maintenance of these different services is huge and repetitive.
Through centralized and straightforward plugins on our gateway, we can converge and unify the different configurations and achieve the effect of reducing operational- and maintenance cost. While providing different security features out of the box, including CSRF, CORS, JWT, LDAP, OpenID Connect, ... enabling security at scale.
Looking at authentication in our OIDC plugin we provide integrations with main Identity Providers like Keycloak, Okta, etc. By straightforward configuration, we provide settings like client ID and client secret after which authentication through said identity provider is fully provided, including permissions and policy enforcement. Giving the underlying backend services back the opportunity to focus solely on what really matters: development of business logic, and delivering core business value to our customers.
Building resilient applications
As architects, we always strive to design systems with the capabilities to avoid catastrophic failures. Unfortunately, in the real world, while interacting with internal-, external- and legacy systems, errors and overloads are almost inevitable causing slow performance or even unavailability. If you have many callers on an unresponsive service, then you can run out of critical resources, leading to cascading failures across distributed components with possible widespread disruptions.
"Everything fails, all the time" - AWS CTO Werner Vogels
As stated in this famous quote: your systems will eventually fail, usually, sooner than later, so it’s best to prepare for the worst. In order to properly handle failures in large-scale systems, we equip ourselves with the right software resiliency practices; circuit breakers help reduce resources tied up in operations that are likely to fail. You avoid waiting on timeouts for the client, and a broken circuit avoids putting load on a struggling server.
The implementation of the circuit breaker pattern can be daunting at first but becomes straightforward while using a unified setup through our API gateway approach. Our API Breaker plugin can be enabled centrally on the API gateway and determines the health of underlying systems based on their behavior in responding to requests while enforcing the three stages of Circuit Breaker known as Closed, Open, and Half-Closed state.
In an Open state, it prevents constant retry attempts on possible unresponsive services while taking into account certain thresholds to move services back to a Half-closed and Closed state when considered fully healthy.
This enables our client applications to handle failures accordingly, improving fault tolerance and increasing overall user experience.
Advanced software architecture
Event-driven architecture is a popular approach that makes use of events to trigger communication between decoupled services. Each service publishes events whenever it updates data, other services subscribe to events acting on them accordingly.
In addition to that, modern applications involve more complex processes including extensive workflows, data validation, and complex business logic that are difficult to express using classical CRUD. As a result, a pattern known as CQRS emerges. Command Query Responsibility Segregation is a pattern that separates Reads and Writes into different models, using Queries to read data and Commands to update data.
This approach helps as query and upsert responsibilities are split into different services, each with its own storage, offering many advantages in case of scalability.
Event-Driven Architecture and CQRS are two different patterns but very successful when used together, accumulating to build large-scale distributed systems. We tend to go for a CQRS approach and apply EDA in addition to suitable projects.
Our API gateway can be utilized to facilitate an optimal CQRS/EDA setup, as it sits between the frontend and backend services. The below diagram illustrates our API gateway implementing resource routing to route read calls to the Query services and upsert calls to the Command services. Where underlying services won’t have to take into account additional CQRS obligations and are able to solely focus on delivering required functionalities.
On top of that, we can implement required services by using both dedicated backend services and serverless functions or a combination. Serverless is a popular architectural style that is rapidly gaining traction when building cloud applications. A FaaS, Function as a Service, allows customers to build, deploy and run their applications without managing the underlying infrastructure.
So in addition to dedicated backend services, we are also able to implement serverless functions as executors of certain events. When configured events arrive at the Event Store, both serverless functions and dedicated backend services can be triggered to handle the event accordingly.
These are some examples of how we leverage our API Gateway approach to build large-scale performant backend systems. Want to know more?