Talks

Moving to GraphQL - the fuzzy parts

Moving to GraphQL - the fuzzy parts

by Greg Kaczorek

In the talk titled "Moving to GraphQL - the fuzzy parts" presented by Greg Kaczorek at RubyDay 2020, the speaker delves into the intricacies of integrating GraphQL with legacy systems, particularly focusing on the challenges and solutions that arise when transitioning from REST APIs.

Key Points Discussed:
- Background on GraphQL: Greg starts by recounting his previous experiences with GraphQL at Toptal, where the transition from REST to GraphQL proved beneficial for both backend and frontend developers due to GraphQL's flexibility and efficiency.
- Need for Standards: He emphasizes the importance of establishing clear standards to maintain consistency across APIs, suggesting the use of enums for predictable outcomes while cautioning against their excessive use.
- Handling Complex Relationships: Different approaches such as simple lists and the concept of connections for cursor pagination are discussed to manage many-to-one relationships effectively.
- Separation of Concerns: Greg advises creating distinct schemas to prevent sensitive data exposure and recommends against one monolithic schema to avoid complications as the API scales.
- Flexibility vs. Complexity: While separation of services allows for flexible development, it may create complexity for users needing to navigate multiple endpoints. He advocates for a single gateway that abstracts these complexities to provide users with a seamless experience.
- Schema Stitching vs. Apollo Federation: He compares schema stitching as a rudimentary merging method with Apollo Federation, which offers a more integrated solution for managing various services within the API.
- API Growth Considerations: As organizations grow, it is crucial to ensure that APIs remain clear and effective without sacrificing usability. Communication among teams is essential to avoid the creation of ugly APIs that can diminish developer morale.
- Practical Challenges and Solutions: Greg also highlights the importance of addressing challenges early in the transition and shares insights on batching functions, error handling in GraphQL, and implementing efficient caching strategies.

Conclusions and Takeaways:
- Transitioning to GraphQL from REST can lead to enhanced flexibility and efficiency, but it requires mindful implementation to avoid common pitfalls.
- A structured approach to API development ensures reusability while safeguarding sensitive data.
- Continuous communication across development teams is vital in overcoming integration challenges and optimizing the GraphQL API experience.

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.