From RESTful to Event-Driven APIs: An Evolutionary Journey

Introduction

Enterprise application landscapes consist of inter-connected and inter-related applications. Over time, the world of application integrations has been constantly evolving towards more efficient and effective integration solutions. This article explores the evolution of APIs from RESTful to event-driven and how this transition modernizes the enterprise.

The Rise of RESTful APIs

Representational state transfer (REST) APIs are effective for basic request-reply commands aimed at a single consumer. RESTful APIs were first introduced in Roy Fielding's doctoral thesis in 2000, and quickly became the standard for building web APIs. REST (Representational State Transfer) is an architectural style that defines a set of constraints for building web services. RESTful APIs provide a uniform interface for accessing resources over HTTP, using standard HTTP methods like GET, POST, PUT, and DELETE. Most contemporary APIs are designed as microservices, a collection of loosely connected services providing business capabilities. Although various architectural styles like GraphQL, gRPC, etc. exist for developing microservices, the preferred choice for most developers and architects is REST.

import requests

response = requests.get("<https://api.example.com/users/1>")
user = response.json()
print(user)
@GetMapping("/books/{id}")
public Book getBookById(@PathVariable Long id) {
    return bookService.getBookById(id);
}

@PostMapping("/books")
public void addBook(@RequestBody Book book) {
    bookService.addBook(book);
}

@PutMapping("/books/{id}")
public void updateBook(@PathVariable Long id, @RequestBody Book book) {
    bookService.updateBook(id, book);
}

APIs have come a long way since the early days of the web. RESTful APIs became the standard for building web APIs, providing a uniform interface for accessing resources over HTTP. However, as the world of software development has evolved, so too have the needs of developers when it comes to APIs. Enter event-driven APIs.

A well-designed microservice should have the following architectural features:

  • Facilitate flexible integration with new functionality through loose coupling

  • Allow multiple distributions of data elements to improve processing efficiency

  • Implement deferred execution to enhance response time, robustness, and performance

  • Ensure dependable delivery for robustness in the face of faults and imbalanced speeds.

However, REST-based microservices may not fully meet these expectations and face challenges such as:

  • Difficulties in inter-process communication

  • Complex and unreliable state in case of failures

  • Slow response time and negative user experience due to complicated orchestration

  • Limited scalability and resource utilization

  • Obstacles in adding new services, leading to a fragmented monolithic architecture

  • The one-to-many pattern can be difficult and unsustainable.

The Need for Event-Driven APIs

While RESTful APIs have been the standard for building web APIs for over two decades, they do have some limitations. One of the biggest challenges with RESTful APIs is the need for continuous polling to check for updates. This can result in increased network traffic and reduced efficiency, especially when dealing with large data sets.

Event-driven APIs address this challenge by enabling applications to respond to changes in data or state in real-time, without having to continuously poll a server for updates. They use a publish-subscribe model, where applications subscribe to events they are interested in, and are notified when those events occur.

Synchronous microservice limitations can be overcome through asynchronous interaction, event-driven architecture, and event-enabling traditional microservices. Event-driven APIs utilize real-time data instead of stored data and are ideal for disseminating time-sensitive information to multiple recipients.

import requests
import json
import asyncio
from aiohttp import ClientSession

async def listen_for_updates():
    async with ClientSession() as session:
        async with session.ws_connect('wss://api.example.com/events') as ws:
            async for msg in ws:
                event = json.loads(msg.data)
                print(event)

asyncio.run(listen_for_updates())
@EventListener(condition = "#event.book.published == true")
public void handleBookPublishedEvent(BookPublishedEvent event) {
    bookService.addBook(event.getBook());
}

@EventListener(condition = "#event.book.published == false")
public void handleBookUnpublishedEvent(BookUnpublishedEvent event) {
    bookService.removeBook(event.getBook());
}

Event-driven APIs enable applications to respond to changes in data or state without having to continuously poll a server for updates. They allow for more efficient and real-time communication between services, enabling developers to build more dynamic and responsive applications.

Events driven APIs deliver the following benefits:

  • Scalability: Event-driven APIs allow systems to scale horizontally, as events can be processed by multiple subscribers in parallel. This makes it easier to handle high volumes of requests.

  • Real-time data: Event-driven APIs enable real-time data processing, enabling systems to respond to events instantly, instead of having to repeatedly poll for updates

  • Decoupled systems: Event-driven APIs promote decoupled systems, as they allow for loose coupling between systems. This means that systems can evolve independently, and changes in one system don’t necessarily impact the other.

  • Flexibility: Event-driven APIs allow for more flexible and dynamic data flow between systems, as events can be generated and processed by different systems, at different times, in different ways.

How to Design Event-Driven APIs

Discovering Events

To improve a system, it is necessary to understand what exists currently. Thus, the first step is a discovery process to identify and document all relevant events. This includes analyzing IT landscape, applications, and business processes to uncover:

  • Data schemas to understand the transported data

  • Topic addresses for accessing and utilizing events

  • Application interfaces for producing, consuming, and processing events

Assessing Usability and Value

After discovering and cataloging all events, they must be evaluated for their potential value and usability. While large enterprises may generate many events, it is important to categorize them as business, system, or technical events. This classification helps to determine the actionable value and worthiness of exposing these events across the enterprise through event streams. Making event streams more accessible and widespread throughout the organization can improve integrated systems and increase synchronization among different parts of the organization.

Bundling and Documenting High Value Events

After identifying high-value events, the next step is to bundle them into a cohesive event API product. By focusing on a problem statement, different events can be combined and processed in a flexible way to deliver business value. As with any API product, it should be easy to:

  • Discover the event API product

  • Document and distribute the event API product in a machine-readable format

  • Manage the event API product

  • Have supporting code generation and developer-focused tools for the event API product.

Release the Event API Product to Generate Value

Here are a few steps to release the event API product:

  • Test the API thoroughly to ensure it meets quality and performance standards.

  • Create documentation that outlines how to use the API, including code examples and API reference.

  • Develop a plan to promote the API to target audience.

  • Set up a system to handle support and feedback from users.

  • Integrate the API with existing systems and platforms.

  • Launch the API and make it available for your target user base.

  • Offer training and support to help users get started.

  • Continuously monitor and improve the API based on user feedback.

Evolve and Optimize the Event API Product

As with any product, there is always scope to improve, processes that change, new use cases that are identified. Managing the lifecycle of your event API product to keep up with these changes is crucial to finding and maintaining success.

Conclusion

Transitioning from synchronous to event-driven APIs unlocks real-time events and information for developers, architects, product owners, and business stakeholders. This evolution positions the enterprise to react quickly and effectively to the fast-paced world.

Did you find this article valuable?

Support Raphael Carlos Rego by becoming a sponsor. Any amount is appreciated!