Ask HN: GraphQL in 2024
Hi, I am the founder of https://tailcall.run. I have personally built and used GraphQL at a massive scale (100M rpm, 1K APIs, 100s services). I believe have a fair understanding of the problem it solves, as well as its pitfalls. We built Tailcall because we realized that manually writing a GraphQL service is inefficient and doesn't scale well. Our main learning was that APIs should be built and operated independently, regardless of how they are consumed.
GraphQL should also be considered as a client-side abstraction and architecturally positioned closer to the client than to the server. In this context, the client could be a mobile app, a website, or even another service querying data from an external or internal data source. As a client-side abstraction, the responsibility of maintenance should lie with the consumer of the APIs, not the producer. All these learnings have helped us architect Tailcall as it is today. Tailcall provides a DSL that allows consumers of the API to configure how they would want the schema to look. Behind the scenes, Tailcall automatically orchestrates the APIs to generate a unified graphQL endpoint. Once configured it can be deployed on a typical server, but semantically still being a piece of the client/API Consumer.
This way of looking at graphQL considers federation as an anti-pattern. GraphQL Federation pushes graphQL towards the server side or more specifically the API producer. This new layer of abstraction also adds significant levels of slowness & complexity in architecture. We started with the problem of clients consuming APIs and the need to compose them, but ended up using a solution that's composing "Graphs". That's not necessarily wrong, but it feels like an overkill for the core problem the organization starts with which is — API Composition.
However, we understand that this might not be relatable for smaller organizations and various others who have been working with GraphQL for a long or probably have a different take on it. I would love to hear your thoughts!
Some of the questions we had were —
Do you prefer to handwrite a graphQL API or, use an open-source solution that could auto-generate a GraphQL endpoint on top of your existing API?
What are your thoughts on GraphQL in general — like, hate, neutral? Does it solve a big problem in your company? Have you tried TRPC as an alternative?
Do you think federation is the future? Based on what you learned, do you think Tailcall is a good design? Looks and feels a lot like AWS Amplify (which is not a bad thing). I assume the difference is that this runs on the frontend server (node) where Amplify tranformation happens on AppSync. Definetly going to test this.
What is bit unclear what is the interface with the frontend server to tailcall,like how do I pass the JWT tokens from node app to @upstream headers? I am not sure if I understand what you by the "frontend server"? I think Tailcall is closer to AppSync than Amplify. Second part of your question: You can define a set of "allowed headers" that will be automatically forwarded upstream. In your case, you can set the allowed headers to `Authorization`. Link to the doc: Your experience with massive-scale GraphQL usage is valuable. Tailcall's approach to API composition is intriguing. Can you share specific scenarios where Tailcall has proven to be particularly effective in comparison to other GraphQL solutions? The idea of tailcall is to move the graphQL abstract closer to the client. So for example, if you are building a web application, you don't need to depend on the backend teams to build a GraphQL implementation for you.
You should be able to use the tailcall DSL and express your orchestration requirements using it. The DSL looks like a normal GraphQL file so there is no new language to learn. Because this file is for the client, it can be literally in the same repository as the client, effectively ensuring the GraphQL server and the client are always on the same version. A simple git ops is then implemented, to auto-deploy the orchestration logic and release the mobile application simultaneously. Because you have a DSL to represent the orchestration logic, you can introspect how the orchestration would happen even before your server starts. So you can apply lint rules on the configuration, and also a ton of ahead-of-time optimizations. You can also identify n + 1 upfront, restrict them in certain cases, and allow for others.
Moreover, you don't need to think about the performance and maintenance of this service. Once deployed on your/our infra, every time there is a configuration change, we just perform a reload and within seconds it is updated across the infrastructure. This is a fundamental shift from how graphQL is maintained traditionally. It gives backend engineers an opportunity to think in terms of orthogonal APIs or migrate from monolith to microservices etc. without worrying. Secondly, it gives frontend engineers the power to design the schema that makes sense for them, without writing any code or being on-call for any outages.