00:00:48.000
We're back with another talk that is quite interesting from my perspective. It's about something old and something new. We all know that we like greenfield projects because they offer endless possibilities. This also means that sometimes you can try whatever technology you want without any big issues. But what if you want to try a new technology alongside something legacy? Usually, those two things don't work necessarily and nicely together. Today, we have Greg to guide us on how to make something as cool as GraphQL work as nicely as possible with legacy code. Hi, Greg! Nice to see you.
00:01:15.360
Greg is going to give a pre-recorded talk, so memorize your questions and share them in the chat. We'll see each other afterwards for a Q&A. See you later!
00:03:54.959
Hello everyone, I'm Greg, and today I'm going to talk to you about growing your GraphQL API and the problems you might encounter. I'm a backend engineer at Toptal, where we've been using GraphQL for a few years now within a pretty big organization. I hope I will be able to help you with your potential issues.
00:04:09.720
I'm very disappointed that we're not in Verona right now; I was hoping to see you all in person. Let's hope that we can meet face to face sometime next year. On the plus side, you'll get to benefit from a few months of additional knowledge from both me and Toptal as an organization. Most of the recommendations I will share here come from our official internal documentation.
00:04:48.400
Let’s start with a bit of history. Four years ago, I gave my first talk on GraphQL. It was about how a small group of backend developers had to support a large team of frontend developers, and we were struggling with REST. We switched to GraphQL just as an experiment, and it turned out that developing GraphQL APIs was better for both backend developers and consumers because they have a more flexible API and don't need us for every change.
00:05:09.600
That was quite important at the time because REST was the dominant paradigm in the Ruby world. I urged my listeners to try out GraphQL and see how it performed. At the end of that presentation, I also mentioned that as you scale your operations with APIs, using GraphQL would definitely benefit you compared to REST. Four years later, my predictions have come true at Toptal. We now have nine schemas.
00:06:02.080
This is our standard—everyone that wants to use something within the organization has to use GraphQL as an API. We have numerous modern frontend applications that rely on it, so everyone inside the organization needs to have some familiarity with it, if not working directly on it. Moreover, we have partially moved our schemas to different services, which introduces a whole new set of scaling issues.
00:06:45.680
In this talk, I want to introduce you to the problems we faced while scaling our API, suggest some possible solutions, and provide recommendations regarding them. However, I won't be able to cover everything in depth, so treat this as a reference for later on.
00:07:29.680
Finally, for those of you who think, 'This probably isn't for me; my API isn't that big,' let me assure you that even if you have a small API, most of this information will still benefit you. It's easy to create an ugly and inconsistent API, and it's even easier to do so when different teams work without proper communication. Remember, our transition to GraphQL wasn't done all at once; it was gradual.
00:08:01.520
We moved one team or one product at a time, hence the complexity can sneak up on you. If you're not cautious, you'll end up with unusable APIs and unhappy developers working with them. An ugly API means lost man-hours and morale, resulting in developers who don't want to work on that API.
00:08:38.680
So let's start with something simple: basic standardization options. Any standard is better than a lack of standards, so write them down somewhere and enforce them within your organization. One step up from that is the use of enums. Enums are fun, predictable, and should be utilized wherever possible. However, don't overdo them; avoid using them in sets that can change.
00:09:25.760
As a frontend engineer, don't rely solely on introspection for enums to guide your implementation. If a value is added to an enum, your code should handle that without breaking. With challenging many-to-one relationships, you can opt for simple lists—a clear and uncomplicated method.
00:10:06.640
Alternatively, there is the concept of connections, a more complex yet standardized approach developed by Facebook for use with Relay, which is about cursor pagination. While more complex, it handles your needs in most cases and is designed to endure changes in the data model.
00:10:43.760
If you prefer a simpler approach, you can always create your own structure without the direct address structure. This gives you a more straightforward interaction to the data while allowing you to abstract specific types for your API. The important takeaway is to use lists only when pagination is unlikely.
00:11:29.280
If you're certain that a client won't have more than a few items, it's reasonable not to implement paging. Otherwise, create a custom pattern that is future-proof and as simple as possible. Ignore connections unless you are working heavily with Relay, as many libraries no longer treat connections as a standard.
00:12:16.960
Sorting, filtering, and pagination aren’t significant challenges—instead, they are more about standards adherence. Once established, enforcing them becomes straightforward. Keep them separate from one another in practice. For example, when implementing a client list, ensure the filter, pagination, and sorting are distinct parameters.
00:12:58.879
Lastly, as your API grows, consider creating different schemas to separate concerns. For illustration, if you have a staff app exposing sensitive information, avoid exposing that information through the same schema to other apps like a talent app to maintain data privacy.
00:13:56.799
This brings the challenge of reusability and exposure of sensitive data. Be cautious, as changes in one app may unintentionally impact another due to shared types used across schemas. It's better to create new types rather than to reuse existing ones with potentially sensitive data.
00:14:41.440
When considering the distribution of a GraphQL API, remember that while it lends more flexibility through separate teams working on different parts, it complicates usage. Consumers must know where to look for related data across services, which they shouldn’t have to manage. Aim for a single graph as a gateway that hides those complexities.
00:15:28.160
Although schema stitching offers a primitive method for merging top-level query objects, using Apollo Federation is a better approach, allowing you to extend and enrich types while achieving clear separation of concerns. Follow these guidelines from the start rather than applying them only when services expand.
00:16:20.880
To summarize, a well-structured API is essential. Avoid using one monolithic schema that leads to complications. Ensure that you've reusability without exposing sensitive data and always account for your organization’s growth. There’s a lot of content left uncovered in this presentation, but these guidelines should help you start building a healthier API.
00:17:29.280
To those of you transitioning to GraphQL, let your experience guide you. Acknowledge the potential problems; it's easier to address them early in the process rather than later. Ask your teams what they want to achieve with GraphQL, define clear approaches, and ensure proper communication across teams.
00:18:12.040
If you run into problems, remember this presentation and the solutions discussed. Investigate the nuances of error handling in GraphQL, both on the top level and on user schemas. This is crucial for standardizing your APIs and enabling smoother interactions between your services.
00:18:48.440
Then, consider how batching functions to avoid common issues such as N+1. If you encounter issues, leverage resources available online, including tutorials on integrating Apollo Federation and service instrumentation in larger organizations.
00:19:25.600
With that, I’ll open the floor to questions!
00:33:18.880
Hi Greg, welcome back! You've provided an extremely interesting and clear presentation. I've noted a question from Twitter regarding whether there are specific cases where you wouldn’t recommend using GraphQL. Could you elaborate on that?
00:34:00.880
GraphQL is beneficial for product-based APIs. If your API is more focused on data processing, REST could still work well. However, in most cases, I find GraphQL to be a better option. It offers much more flexibility and efficiency.
00:34:26.240
Thank you for that insight! We've discussed whether to stick with REST or move to GraphQL, particularly regarding the abstraction of our APIs. You’ve mentioned the significance of using a gateway pattern in your earlier slides.
00:34:41.760
We've experienced challenges with REST as we are scaling, as it often forced us to tweak endpoints to accommodate frontend needs, resulting in inefficiencies that GraphQL can reduce.
00:35:06.560
Earlier in our development, we felt obligated to expose too many fields due to REST's limitations. We’ve noticed that GraphQL allows frontend users access to precisely what they need without overwhelming them.
00:35:51.600
And finally, regarding implementation, do you typically implement GraphQL in Ruby or JavaScript? There are perceptions that JavaScript has better support for flexibility and performance.
00:36:14.720
At Toptal, all APIs are implemented in Ruby, as that's the language our developers are most comfortable with. However, you can leverage federation to integrate faster services built in other languages when necessary.
00:37:04.720
An important reminder is that while SQL or other databases might require eager loading, this is still manageable within GraphQL through batching logic. Eager loading works well when you know certain queries will always be needed.
00:37:50.720
In terms of HTTP caching, GraphQL itself doesn't offer this feature inherently due to its structure of requiring POST requests for queries, which limits its cacheability. However, there are ways to implement caching at the query level.
00:38:45.760
To conclude, even if we move towards GraphQL, we should be mindful of ongoing questions about growth. As we implement these changes, we should be prepared for challenges while seeking options to alleviate them. Thank you for your time!
00:39:28.640
Thank you, Greg, for an insightful session full of practical advice! Looking forward to applying this knowledge.