LUC #28: GraphQL vs REST: Navigating the Evolving Landscape of API Design
Plus, how SSO works, the main components of Docker explained, and the most used caching eviction policies, and how they work
Welcome back, fellow engineers! We're excited to share another issue of Level Up Coding’s newsletter with you.
In today’s issue:
GraphQL vs REST: Navigating the Evolving Landscape of API Design
How SSO (Single Sign-On) Works (Recap)
READ TIME: 8 MINUTES
GraphQL vs REST: Navigating the Evolving Landscape of API Design
The year 2000 forever changed the API landscape. It was the year REST was born. The “rest” is history (bye-bye SOAP). REST has been the predominant architecture for APIs for the past couple of decades, but there has been an alternative solution growing in popularity since 2015 — GraphQL.
GraphQL is technically not an API architectural style, but rather a query language for APIs. It offers a flexible approach for data access and manipulation, contrasting with the structured architectural constraints and principles of other architectural patterns. This positions GraphQL as an alternative tool to REST and other API architectures for API interactions.
Now, let’s dive into the nuances of REST and GraphQL, their distinct characteristics, the upsides and downsides of each, and where each technology shines best.
Representational State Transfer (REST) is an architectural style that is commonly used for web-based APIs alongside HTTP as the transport protocol.
Below are some of the hallmark characteristics of REST:
Statelessness: Essential to REST, statelessness dictates that the server should not store any user information between requests. Each request from the client must contain all the necessary information for the server to process it.
Separation of concerns: REST enforces a clear division where the client and server operate independently, enhancing modularity and facilitating maintenance.
Uniform interface: RESTful APIs utilize standard HTTP methods like GET, POST, and DELETE, ensuring a uniform and predictable interface.
Resource-based approach: Central to REST is its focus on resources — objects, entities, or data within a system, each uniquely identified by URIs. This contrasts with approaches centered around methods or functions.
Standard media types: RESTful APIs typically communicate using standard formats like JSON, XML, or plain text, with the ability to handle various media types as per client requests. This standardization simplifies the interaction and parsing of responses.
The Good and the Bad of REST
REST offers many benefits, below are a few of the primary benefits:
🔷 Simplicity and flexibility: Leveraging standard HTTP methods, makes it easy to understand and implement. It also supports multiple data formats.
🔷 Scalability: Its stateless nature allows REST services to handle a large volume of requests and horizontally scale with ease.
🔷 Cacheability: By enabling responses to be cached on the client side, REST significantly boosts performance and reduces server load.
As with all technologies, there are inescapable downsides:
🔶 Over-fetching and under-fetching: REST APIs can return excessive data (over-fetching) or require multiple calls for complex data (under-fetching).
🔶 Rigid structure: Adhering to RESTful principles can sometimes lead to inflexibility in API design and implementation.
🔶 Less efficient for complex queries: REST can be less efficient for applications that require complex queries to aggregate data from multiple sources, as this often necessitates multiple API calls.
Introduced by Facebook in 2015, GraphQL presents a new way of building APIs. In some ways, GraphQL can feel like the opposite of REST.
Contrary to the REST approach, which can necessitate multiple requests to obtain interconnected data, GraphQL provides a more streamlined method. Rather than having multiple endpoints for each resource or entity, it provides a single endpoint.
GraphQL provides strong typing enforced by a schema that clearly defines available data types and their query formats, ensuring structured and predictable interactions. This allows users to define their specific data requirements. In response, resolvers will then fetch the actual data, which can come from a variety of sources and the server will package the data to match the structure that the client requested.
It efficiently delivers the requested data in a single query. Rather than over-fetching and under-fetching data, you get only what you require. This precision in data retrieval improves performance as well as user experience.
The Upsides and Downsides of GraphQL
There are some strong benefits GraphQL provides over a REST approach:
🔷 Efficient data loading: Ideal for applications with complex data structures and relationships, minimizing over-fetching and under-fetching issues.
🔷 Single network request: Multiple data needs can be consolidated into a single network request, reducing the overhead of multiple API calls.
🔷 Real-time data with subscriptions: GraphQL supports real-time updates, a feature not inherently present in REST.
🔷 Rapid front-end development: Front-end teams can make data changes without heavy reliance on back-end modifications.
However, there are also some drawbacks and challenges that need to be fully taken into consideration:
🔶 Performance issues with complex queries: Complex queries in GraphQL can sometimes lead to performance problems, particularly if not properly managed or optimized.
🔶 Caching challenges: Unlike REST, which can easily leverage HTTP caching, GraphQL requires more sophisticated strategies for effective caching.
🔶 Added complexity: GraphQL adds a layer of complexity to the system in comparison to REST.
🔶 Steep learning curve: The paradigm shift GraphQL introduces can require a significant investment in learning and adaptation.
Comparing REST and GraphQL: The Context Matters
When it comes to choosing between REST and GraphQL, the decision hinges on the specific requirements of your application.
Ideal Use Cases for REST
Web services and APIs: REST is well-suited for building standard web services and APIs, especially for Internet-facing applications.
Microservices architecture: Its stateless nature and scalability make REST ideal for microservices-based distributed systems.
CRUD applications: REST is a natural fit for applications with a clear resource model and straightforward CRUD (Create, Read, Update, Delete) operations.
Mobile applications: RESTful APIs provide a lightweight and flexible way to serve data to mobile apps, accommodating varied network conditions.
Legacy system compatibility: REST’s maturity means it's often more compatible with older systems and technologies.
Optimal Scenarios for GraphQL
Applications with complex, interrelated data: GraphQL excels in environments where clients need to retrieve nested or interrelated data in a single request.
Real-time applications: Such as chat apps or live data feeds, benefit from GraphQL's real-time data updates with subscriptions.
Rapidly evolving front-end requirements: The flexibility of GraphQL is particularly advantageous in fast-paced development environments, where the ability to quickly adapt and iterate on the front-end without extensive back-end changes is crucial.
Microservices architectures: Useful for aggregating data from various microservices into a unified API layer.
GraphQL and REST operate in distinctly different approaches to data access and manipulation. This gives rise to a distinct set of advantages and tradeoffs for each, as well as different scenarios in which they perform best.
REST stands as a proven, reliable choice for standard web services in both simple applications and complex systems, with simplicity being a standout feature.
On the other hand, GraphQL is a powerful alternative for applications requiring complex data retrieval and real-time interactions, but it can add a lot of complexity.
How SSO (Single Sign-On) Works (Recap)
SSO can be thought of as a master key to open all different locks. It allows a user to log in to different systems using a single set of credentials. In a time where we are accessing more applications than ever before, this is a big help to mitigate password fatigue and streamlines user experience.
There are three key players in SSO: the User, the Identity Provider (IdP), and the Service Providers (SP).
The Main Components of Docker Explained (Recap)
Software inconsistencies across different environments lead to significant issues including deployment failures, increased development and testing complexity, and more. Docker solves the "it worked on my machine" problem, and streamlines application deployment by encapsulating applications and their dependencies into standardized, scalable, and isolated containers (containerization).
Below are the core components powering Docker:
Image: A read-only template for creating containers. Contains application code, libraries, and dependencies.
Container: An instance of an image. It is a lightweight and standalone executable package that includes everything needed to run an application.
Dockerfile: A script-like file that defines the steps to create a Docker image.
Docker engine: Responsible for running and managing containers. Consists of the daemon, a REST API, and a CLI.
Docker daemon: A background service responsible for managing Docker objects.
Docker registry: Repositories where Docker images are stored and can be distributed from; can be private or public.
Docker network: Provides the communication gateway between containers running on the same or different hosts; allowing them to communicate with each other and the outside world.
Volumes: Allow data to persist outside of containers and to be shared between container instances.
The Most Used Caching Eviction Policies, and How They Work (Recap)
How data is updated and cleared is a key component of the design of any caching strategy. Here are five of the most popular caching eviction approaches:
🔶 Least Recently Used (LRU) - This strategy deletes the oldest unused data to make room for new content. It operates on the premise that data accessed recently will likely be needed again soon.
🔶 Most Recently Used (MRU) - Contrary to LRU, MRU removes the most recently utilized data first and suits scenarios where once-used data isn’t needed again, like in streaming services.
🔶 Least Frequently Used (LFU) - LFU evicts the least frequently accessed data. It is more precise than LRU but adds complexity due to the need for tracking access frequency.
🔶 Time-To-Live (TTL) - TTL sets a predefined lifespan for stored data, ideal for information that becomes obsolete after a certain time, such as session data.
🔶 Two-Tiered Caching - This complex system divides data between 2 tiers, a high-speed, costly cache for frequently accessed data and a slower, cost-effective cache for less popular data.
These strategies are also worth mentioning:
🔹 First in, First Out (FIFO): The oldest data is deleted first.
🔹 Random Replacement (RR): Randomly selects data to be deleted.
🔹 Adaptive Replacement Cache (ARC): Uses a self-tuning algorithm that tracks recency and frequency to determine which data to delete first.
That wraps up this week’s issue of Level Up Coding’s newsletter!
Join us again next week where we’ll explore understanding deployment patterns, webhook vs polling, SOLID principles, and protecting against DDoS attacks.