I'm implementing it as a POC in my company, Apollo Federation.
And I'm not finding in the documentation how to do the health check of the subgraph so that there is no error when uploading the gateway.
Is there any way to do it?
my example: https://user-images.githubusercontent.com/47068314/188695650-4181bbab-7cb1-4ee9-b81a-f555231f3701.png
We actually implemented a health check resolver in each of our subgraphs, where if the subgraph name is Orders the health check is a query named ordersHealthCheck.
There are a few nice things about this - one is that it uses Federation fully and two is that it's extendable. We've abstracted everything into a packaged class that can be extended to check for third party API connectivity and other things as part of the check.
Related
We recently switched our tech stack from multiple, fully-encapsulated microservices to Apollo Federation. Each microservice was converted to a subgraph and the supergraph is federated by the gateway.
But lately it feels like we've lost some of the major pluses of working with microservices-- decoupled deployments, async inter-service communication, tons of extra wiring and time spent coordinating development to keep the supergraph stable across multiple environments.
It feels like we've regressed to a more monolithic style of working, but with independent teams and services.
Since Apollo hasn't been around for a while, and was developed against the GraphQL spec, which was initially intended to speed up Facebook's latency issues back when it was a monolith, I can't help but wonder if it's just not in a place yet to fully support microservice architectures. I sometimes wonder if it's overkill to do both Apollo Federation and microservices.
TL;DR:
Is using Apollo Federation with microservices just a bleeding-edge buzzy endeavor with diminishing returns on investment or does it make actual sense?
What are the (I imagine small number of) use cases in which doing this would make sense?
How do we retain benefits of working with pure microservices (namely, not coordinating small changes across tons of services in lockstep) in a Federation paradigm?
How do we retain benefits of working with pure microservices (namely, not coordinating small changes across tons of services in lockstep) in a Federation paradigm?
I believe that Apollo Federation is mainly useful due to the principle of separation of concerns. With this, you do not need to coordinate small changes across tons of services in lockstep. For example, say you have a Reviews subgraph and a Users subgraph. As long as the two subgraphs know the key for the other entity, they can use it without needing to coordinate changes amongst themselves. If team A implements things related to only their concern, they should ideally never have to coordinate a change with another team.
Is using Apollo Federation with microservices just a bleeding-edge buzzy endeavor with diminishing returns on investment or does it make actual sense?
If you already have microservices which are completely independent of each other, using Apollo Federation may not be the ideal tool you might want to go with. There are other open source solutions out there that would help you combine your microservices under a single gateway (such as GraphQL-mesh, Stepzen, etc.) - and these do not require your microservices to support federation. That being said, there are teams out there that still stick with Apollo Federation because of its innate ability to help separate out subgraphs in a relatively clean way though the concept of ownership separation of concerns. So there are definitely use cases (i.e. when one subgraph has to use an entity owned by another subgraph) where using Apollo Federation has an impact.
I'm new to both concepts so excuse me if it's opinion-based. Currently, I'm looking at Apollo Federation and schema stitching provided by the graphql-tools package, though I guess it applies to similar packages. Could something like a table be created describing certain requirements/conditions to prefer one over the other?
Apollo's GraphQL Federation and "schema stitching" both accomplish a similar goal: unify multiple GraphQL APIs under a single GraphQL API.
Based on my understanding, the main differences between them are:
In Apollo's Federation, subgraph services own the logic for linking shared types together; in schema stitching, this logic is handled by the gateway.
Apollo's Federation distributes the ownership of subgraphs to the individual service teams; stitching assumes centralized responsibility of the full schema.
Apollo's Federation is tightly coupled to the Apollo ecosystem; GraphQL Tools' schema stitching is more open source.
For more details, I'd recommend reading https://product.voxmedia.com/2020/11/2/21494865/to-federate-or-stitch-a-graphql-gateway-revisited.
I am trying to wrap my head around the differences between an API gateway and the aggregator pattern for microservices.
At the moment From my understanding the aggregator pattern functions by collecting pieces of data from various microservices and returns an aggregate for processing.
Now the API gateway is the single entry point that aggregates the calls to the individual microservices. While this may sound very similar to the Aggregator Pattern, there are some distinct features. Most importantly, this new service does not store data but instead becomes responsible for API composition, request routing, and new features such as authentication
I would really like to understand if my reasoning is correct here.
Thank you in advance!
Yes, your understanding is correct. I would add a few ideas:
The API Gateway usually is entry-point of the system, while an aggregator microservice can be somewhere in the middle-layer.
The API Gateway may store partial responses from other microservices, while it waits for other ones to respond (similarly to an aggregator)
There is also a pattern which mixes them, known as a gateway aggregation pattern
Though this seems very similar having a aggregator service vs API Gateway acting as a aggergator.
Think about much bigger ecosystem, where API Gateway would genrally be 1, but we can have number of aggregator services.
Aggregator service will generally lie in middle layer and can be built using specific patterns, these can be Parallel, Chaining or Branching.
Taking example of ecommerce application, we can have below aggregators and more.
Customer Dashboard Aggrgator (Recommeneded products, past orders, current active order etc)
Cart Aggregator (Shipping Service, Inventory Service, Discount Service)
Order History Aggregator
Customer Information Aggregator (Personal Information, Address)
This is probably a bit opinion-based question, but I will try to be technical to still be relevant.
Consider having several microservices: a, b, c.
To make this available on frontend, these could be made available as:
https://host/services/a
https://host/services/b
https://host/services/c
However, the fact that the endpoints are split between differents services are kind of irrelevant for frontend and basically if we can guarantee the endpoints don't clash, it would be great to have these available directly:
a/endpoint1 -> https://host/services/endpoint1
a/endpoint2 -> https://host/services/endpoint2
b/endpoint3 -> https://host/services/endpoint3
c/endpoint4 -> https://host/services/endpoint4
To implement such mapping, one needs to list all endpoint or at least write some matching pattern within the proxy service. This is very nice for the Frontend team to work with, however it is unfortunately very easy to brake.
What are the best practices for mapping the urls of microservices? Only thing which comes to my mind are some exports of OpenApi, which could be handled by FE to get the right path. However, every service generates its own OpenApi json, so we are basically back to the original problem.
are you sure the Frontend team needs ALL the exposed endpoints? Usually, frontends talk with an API Gateway, or, as cool kids call them these days, "Backend for Frontends".
In a nutshell, it's a special service that takes care of exposing only the functionalities/endpoints needed by the frontend. It will forward calls to the relevant services or, if necessary, call multiple services and aggregate the results.
In most cases these API Gateway don't have a db, as they're retrieving all the data from other services. They might however make use of a caching layer to speedup things.
You can even have multiple API Gateway, one per Frontend (eg. desktop, mobile).
In a micro-service architecture, I do have GraphQL mutations that are deemed to be used by the end-user, and some more that are only internal.
I am planning to move to Apollo Federation. Is there a built-in way to declare a mutation as unexpected, so that it is not accessible to the end-user but can be called by an internal service directly?
I am not sure what the best design for this would be ; I would not want ending up in a situation for which I have to run two different servers for micro services: a public and a private one.
In short: No, there is not a built-in or conventional way to declare parts of your schema as "private." You could devise your own #private schema directive, which could wrap resolvers with an authentication check that requires a service API key rather than a user access token. These mutations would still be visible on in your schema — that is, they will likely appear in any automatically generated API documentation — but they would be effectively unusable by regular users. In this Apollo Server issue, an Apollo dev mentions plans to provide a built-in #internal directive for this purpose, but it doesn't seem to be available yet.