---
title: Blog - Trusted Team Extension Partner For Europe & USA | GraphQL
description: GraphQL | Empower your business with our expert team augmentation services. Scale efficiently and stay ahead in the ever-evolving tech landscape.
---

[Skip to content](https://www.craftsmensoftware.com/blog/tag/graphql#main)

\[ CLIENT STORY \]

CLOSE ✕

[![Craftsmen](https://crafty-astro-2-0.skarif2.workers.dev/_astro/logo.CZgI5u57_1oRGAt.webp)![Craftsmen](https://crafty-astro-2-0.skarif2.workers.dev/_astro/logo-dark.B-8biif6_paamB.webp)](https://www.craftsmensoftware.com)

[About us↗](https://www.craftsmensoftware.com/about-us)[Client Stories↗](https://www.craftsmensoftware.com/client-success-stories)[Case Study↗](https://www.craftsmensoftware.com/en-us/case-studies)[How We Work↗](https://www.craftsmensoftware.com/how-we-work)[Blog↗](https://www.craftsmensoftware.com/blog)[Career↗](https://careers.craftsmensoftware.com/)

![](https://www.craftsmensoftware.com/hubfs/norway.svg)NO

[Get In Touch↗](https://www.craftsmensoftware.com/contact-us)MENU

[About us↗](https://www.craftsmensoftware.com/about-us)[Client Stories↗](https://www.craftsmensoftware.com/client-success-stories)[Case Study↗](https://www.craftsmensoftware.com/en-us/case-studies)[How We Work↗](https://www.craftsmensoftware.com/how-we-work)[Blog↗](https://www.craftsmensoftware.com/blog)[Career↗](https://careers.craftsmensoftware.com/)

![](https://www.craftsmensoftware.com/hubfs/norway.svg)NORSK

[Get In Touch↗](https://www.craftsmensoftware.com/contact-us)

# Insights on Software, Teams*and Technology Growth*

Explore practical perspectives on software delivery, team collaboration, and technology partnerships that help growing businesses make better decisions and build with confidence.

[Discuss Your Needs](https://www.craftsmensoftware.com/contact-us)

![Craftsmen engineers and international partners on stage at Tech for Good in Bergen](https://www.craftsmensoftware.com/hs-fs/hubfs/Software%20Team%20Norway%2c%20UK%2c%20USA%2c%20Sweden.jpg?width=2000&name=Software%20Team%20Norway%2c%20UK%2c%20USA%2c%20Sweden.jpg)

Search articles

[All](https://www.craftsmensoftware.com/blog#articles) [Blog](https://www.craftsmensoftware.com/blog/tag/blog#articles)[AWS](https://www.craftsmensoftware.com/blog/tag/aws#articles)[Tech](https://www.craftsmensoftware.com/blog/tag/tech#articles)[Python](https://www.craftsmensoftware.com/blog/tag/python#articles)[Tips and hacks](https://www.craftsmensoftware.com/blog/tag/tips-and-hacks#articles)[lambda](https://www.craftsmensoftware.com/blog/tag/lambda#articles)[Software Team Augmentation](https://www.craftsmensoftware.com/blog/tag/software-team-augmentation#articles)[DynamoDB](https://www.craftsmensoftware.com/blog/tag/dynamodb#articles)[Team Augmentation](https://www.craftsmensoftware.com/blog/tag/team-augmentation#articles)[AI](https://www.craftsmensoftware.com/blog/tag/ai#articles)[Nodejs](https://www.craftsmensoftware.com/blog/tag/nodejs#articles)[serverless](https://www.craftsmensoftware.com/blog/tag/serverless#articles)[React](https://www.craftsmensoftware.com/blog/tag/react#articles)[Flask](https://www.craftsmensoftware.com/blog/tag/flask#articles)[GraphQL](https://www.craftsmensoftware.com/blog/tag/graphql#articles)[FFmpeg](https://www.craftsmensoftware.com/blog/tag/ffmpeg#articles)[Git](https://www.craftsmensoftware.com/blog/tag/git#articles)[GoLang](https://www.craftsmensoftware.com/blog/tag/golang#articles)[SQL](https://www.craftsmensoftware.com/blog/tag/sql#articles)[Transcription](https://www.craftsmensoftware.com/blog/tag/transcription#articles)[Vite](https://www.craftsmensoftware.com/blog/tag/vite#articles)

GraphQL2 articles

[![](https://www.craftsmensoftware.com/hubfs/Imported_Blog_Media/End-to-End-Guide-Building-and-Deploying-GraphQL-APIs-with-AWS-AppSync-and-Serverless.webp)](https://www.craftsmensoftware.com/blog/end-to-end-guide-building-and-deploying-graphql-apis-with-aws-appsync-and-serverless)

### [End-to-End Guide: Building and Deploying GraphQL APIs with AWS AppSync and Serverless](https://www.craftsmensoftware.com/blog/end-to-end-guide-building-and-deploying-graphql-apis-with-aws-appsync-and-serverless)

In this blog post, we’ll explore how to build and deploy GraphQL APIs using AWS AppSync and the Serverless Framework. This tutorial is designed to be easy to follow for both beginners and experienced developers. By the end, you’ll have a working GraphQL API deployed on AWS. Introduction to GraphQL GraphQL is an open-source query and data manipulation language developed by Facebook, GraphQL allows you a more flexible and feasible way to fetch and manipulate data compared to traditional API calls. It allows you to request the exact data you need. With GraphQL you as a client can specify the structure of data you want to receive, and the server will return only that data. GraphQL is built with a strongly typed schema. That defines the type and relationships of data that can be queried. Clients interact with schema using mutations, queries, and subscriptions. Key Concept of GraphQL Query Language for APIs GraphQL allows you to specify exactly what data you want in a single request. You can fetch the data you need in a single query and avoid multiple roundtrips to the server. Single Endpoint Not like REST APIs, which often require multiple endpoints for different resources, GraphQL APIs have only a single endpoint. Clients send their queries to the endpoint that GraphQL provides, and the server will process the query and return the appropriate response you need. Strongly Types Schema The schema we use in GraphQL is defined using GraphQL Schema Definition Language (SDL). This schema definition includes various types, queries, mutations, and subscriptions. Each type can have fields, which can themselves be complex types or simple scalar types like strings, integers, and booleans. Queries GraphQL queries allow you as a client to request specific fields you need from a resource and nested resources in a single request. A query mirrors the shape of the response the client expects. Below is a simple query example:   { posts { id title Content } } Copy This query will fetch posts and retrieve their ID, title, and content of their posts. Mutations Mutations allow clients to modify data on the server side. They are similar to queries; queries allow clients to fetch data, but mutations allow clients to create, update, and delete data. Mutation also specifies the data that should be returned after modification. Here’s an example of a mutation to create a new post: mutation CreatePost { createPost(title: "Sample Post", content: "This is a sample Post", author: "Jone") { id title Content author } Copy   Subscriptions Subscriptions allow clients to receive updated data in real time from the server. This is useful for applications that need to react to changes in data, such as chat apps or live sports scores. Subscriptions use WebSockets to push updates to the clients whenever specified events occur. subscription { newPost { id title content } } Copy   Resolvers Resolver is noting it’s a function that connects GraphQL queries and mutations to your backend data. When a query is made, GraphQL calls the appropriate resolver to fetch the requested data. Resolver can fetch data from databases, APIs, or any other data source. Advantages of GraphQL GraphQL runs faster GraphQL is significantly faster than other communication APIs because it allows you to narrow down your request query by selecting only the fields you want to query. Best for complex systems and microservices We can combine multiple systems behind GraphQL’s API. It unifies them and hides their complexity. The GraphQL server is also used to fetch data from the existing systems and package it up in the GraphQL response format. This is most beneficial for legacy infrastructures or third-party APIs that are enormous in size and difficult to maintain and handle. When we have to migrate from a monolithic backend application to a microservice architecture, the GraphQL API can help us to handle communication between multiple microservices by merging them into one GraphQL schema. Efficient Data Fetching The main advantage of GraphQl over REST is that REST responses contain too much data or sometimes not enough data, which creates the need for another request. GraphQL solves this problem by fetching only the exact and specific data in a single request. Single End Point Having a single endpoint simplifies the client-server interaction; clients do not need to manage multiple endpoints for different resources; we can manage multiple resources in a single endpoint. Real-Time Data Built-in support for subscriptions allows clients to receive real-time updates, which is essential for many modern applications. Understanding AWS AppSync AWS AppSync is a managed service that uses GraphQL to make it easy for applications to get exactly the data they need. It automatically scales your GraphQL API and provides real-time updates with built-in data synchronization. Key Features of AWS AppSync Managed GraphQL Service This service abstracts away all of the runtime semantics and operational challenges of a GraphQL API, making it painless for developers. Real-Time Data It supports GraphQL subscriptions. This way, you can build real-time applications simply. Integration with AWS Services Integration is no challenge since the API is perfectly compatible with AWS services such as DynamoDB, Lambda, and Cognito which turn your machine into a platform for applications of any scale. Now that we’ve covered the fundamentals of GraphQL and AppSync, let’s take a step-by-step approach to creating a backend application for our blog posts. Step 1: Setting Up Your AWS Environment Before we dive into creating our GraphQL API, we need to set up our AWS environment. This includes creating an AWS account and configuring the necessary services. Step-by-Step: Setting Up AWS Log in to the AWS Management Console If you don’t have an AWS account, sign up for a free account. Once you have an account, log in to the AWS Management Console. Navigate to AppSync In the AWS Management Console, search for “AppSync” in the AWS services search bar and click on it. Step 2: Creating a GraphQL API Now that our AWS environment is set up, let’s create our GraphQL API using the AppSync console. We’ll start by defining a simple schema and then add data sources and resolvers. Step-by-Step: Creating a GraphQL API Create a new API Click “Create API” and choose “Start from scratch.” This will allow us to define our own schema and resolvers. Define the API name Enter a name for your API (e.g., “MyBlogPostAPI”). This will be the name used to identify your API in the AWS Management Console. Step 3: Define the API schema In the AppSync console, you’ll be prompted to define your API schema. You can start with a sample schema or create your own. For this guide, let’s start with a simple schema for a Blog Post application. type Post { id: ID! title: String! content: String! author: String! } type Query { posts: \[Post\] } type Mutation { createPost(title: String!, content: String!, authorId: String!): Post } type Subscription { newPost: Post } schema { query: Query mutation: Mutation subscription: Subscription } Copy   This schema defines a Post type with id, title, content, and author fields. It also defines a Query type for fetching posts and a Mutation type for creating posts. Save the schema Click “Save” to save your schema. AppSync will validate your schema and provide feedback if there are any errors. Step 4: Adding Data Sources A data source is a persistent storage system (like DynamoDB, RDS, etc.) where the data for your API resides. Resolvers connect the fields in your schema to your data source. Step-by-Step: Adding Data Sources Navigate to Data Sources Click on the “Data Sources” tab in the AppSync console and then click “Create Data Source.” Select DynamoDB For this example, choose DynamoDB as your data source and enter a name for it (e.g., “BlogPostTable”). If you don’t already have a DynamoDB table, you can create one through the DynamoDB console. Navigate to the DynamoDB service, click “Create table,” and configure it with a partition key of pk and sort key of sk(type: String).   { "TableName": "PostTable", "AttributeDefinitions": \[ { "AttributeName": "pk", "AttributeType": "S" }, { "AttributeName": "sk", "AttributeType": "S" } \], "KeySchema": \[ { "AttributeName": "pk", "KeyType": "HASH" }, { "AttributeName": "sk", "KeyType": "RANGE" } \] } Copy Step 5: Creating Resolvers Resolvers are functions that handle requests for data. There are two types of resolvers unit and pipeline resolvers. Unit resolvers A unit resolver is composed of code that defines a single request and response handler that are executed against a data source. The request handler takes a context object as an argument and returns the request payload used to call your data source. The response handler receives a payload back from the data source with the result of the executed request. The response handler transforms the payload into a GraphQL response to resolve the GraphQL field. Pipeline Resolvers When implementing pipeline resolvers, the general structure they follow includes: Before Step: Preprocesses request data before it moves through the resolver. This allows initial operations to be performed. Function(s): After the before step, the request is passed to a list of functions. Each function has its own request and response handler: Request Handler Performs operations against the data source. Response Handler Processes the data source’s response before passing it to the next function. Functions They execute serially in the order defined by the developer. The final result is passed to the after step. After Step A handler function that performs final operations on the response from the last function before passing it to the GraphQL response. We’ll need to create a resolver for each field in our schema that interacts with our data source. We’ll use unit resolvers and AppSync JavaScript (APPSYNC\_JS) as the resolver runtime. Add a resolver for createPost: In your API, choose the Schema tab. In the Resolvers pane, find the createPost field under the Mutation type, then choose Attach. Choose your data source, then choose Create. In your code editor, replace the code with this snippet:   import { util } from "@aws-appsync/utils"; import \* as ddb from "@aws-appsync/utils/dynamodb"; function request(ctx) { const { input } = ctx.arguments; const id = util.autoId() const sk = \`${id}\`; const item = { id, ...input }; const key = { pk: "POST", sk }; return ddb.put({ key, item }); } function response(ctx) { return ctx.result; } export { request, response }; Copy To Add a resolver for posts: In your API, choose the Schema tab. In the Resolvers pane, find the posts field under the Query type, then choose Attach. Choose your data source, then choose Create. In your code editor, replace the code with this snippet:   import \* as ddb from '@aws-appsync/utils/dynamodb' export function request(ctx) { return ddb.get({ key: { pk: "POST" } }) } export const response = (ctx) =\> ctx.result Copy Testing Your GraphQL API AWS AppSync provides a built-in GraphQL playground to test your API. This playground allows you to run queries and mutations against your API and see the results in real-time. Step-by-Step: Testing the API Navigate to the Queries Tab In the AppSync console, go to the “Queries” tab. This will open the GraphQL playground Run a Query: Enter the following query to fetch all posts: query ListPost { posts { id title Content author } } Copy   2. Click the “Run” button to execute the query: You should see an empty list if no posts have been created yet. Run a Mutation: Enter the following mutation to create a new post: mutation CreatePost { createPost(title: "Sample Post", content: "This is a sample Post", author: "Jone") { id title Content author } Copy Click the “Run” button to execute the mutation. You should see the new post in the response. Run the Query Again: Run the ListPost query again to see the newly created post in the list. Deploying Blog Post Applications with Serverless The Serverless Framework simplifies the deployment and management of serverless applications. It allows you to define the infrastructure as code and deploy it with a single command. Now we will deploy our Blog post application using the serverless framework here are the steps we need to follow. Step-by-Step: Deploying with Serverless Install Serverless Framework: If you haven’t already, install it globally using npm.   npm install -g serverless Copy 2. Create a Serverless Project: Initialize a new Serverless project. serverless create --template aws-nodejs --path graphql-appsync cd graphql-appsync Copy   3. Instal Dependencies: Install the AWS AppSync plugin for Serverless. npm install serverless-appsync-plugin Copy   4. Configure serverless.yml: Edit the serverless.yml file to include the AppSync plugin and configure your API. First of all, set up the service name as blog-post and specify that you are using version 3 of the Serverless Framework. service: blog-post frameworkVersion: "3" Copy   The provider section defines AWS as the cloud provider, sets the region to us-east-1, and specifies Node.js version 20.x as the runtime environment for your application. provider: service: blog-post frameworkVersion: "3" Copy plugins section includes the AppSync plugin to enable integration with AWS AppSync. plugins: - serverless-appsync-plugin Copy   The appSync section configures your AppSync API, naming it blog-post-api, using API\_KEY for authentication, and defining an API key that expires after one month. appSync: name: blog-post-api authentication: type: "API\_KEY" apiKeys: - name: blog-post-key expiresAfter: 1M Copy   The resolvers section specifies how to handle GraphQL operations: Mutation.createPost Defines a unit resolver for the createPost mutation, using postTable as the data source and referencing the code in resolvers/createPost.js. Query.posts: Defines a unit resolver for the posts query, also using postTable as the data source, with the implementation in resolvers/getAllPost.js. resolvers: Mutation.createPost: kind: UNIT dataSource: postTable code: resolvers/createPost.js Query.posts: kind: UNIT dataSource: postTable code: resolvers/getAllPost.js Copy The resources section defines a DynamoDB table named BlogPost with a primary key (pk) of type string and specifies the key schema for the table. resources: Resources: MyTable: Type: AWS::DynamoDB::Table Properties: TableName: BlogPost AttributeDefinitions: - AttributeName: pk AttributeType: S - AttributeName: sk AttributeType: S KeySchema: - AttributeName: pk KeyType: HASH - AttributeName: sk KeyType: RANGE BillingMode: PAY\_PER\_REQUEST Copy 5. Create Schema File: Create a file named schema.graphql in the root of your project and paste the above schema. 6. Create Resolves: Create a folder named resolvers in the root of your project and create two js files one is createPost.js and another one is getAllPost.js and paste the resolvers code that we define above. 7. Deploy Your Service: Run the deploy command to deploy your API. Serverless Deploy This command will package and deploy your service to AWS. The Serverless Framework will provide the API endpoint after deployment. Retrieve the Endpoint: After deployment, the Serverless Framework will output the API endpoint. You can use this endpoint to interact with your GraphQL API. Full Code:   service: blog-post frameworkVersion: "3" provider: name: aws region: us-east-1 runtime: nodejs20.x plugins: - serverless-appsync-plugin appSync: name: blog-post-api authentication: type: "API\_KEY" apiKeys: - name: blog-post-key expiresAfter: 1M schema: "schema.graphql" dataSources: postTable: type: AMAZON\_DYNAMODB description: "Blog Post Table" config: tableName: BlogPost resolvers: Mutation.createPost: kind: UNIT dataSource: postTable code: resolvers/createPost.js Query.posts: kind: UNIT dataSource: postTable code: resolvers/getAllPost.js resources: Resources: MyTable: Type: AWS::DynamoDB::Table Properties: TableName: BlogPost AttributeDefinitions: - AttributeName: pk AttributeType: S - AttributeName: sk AttributeType: S KeySchema: - AttributeName: pk KeyType: HASH - AttributeName: sk KeyType: RANGE BillingMode: PAY\_PER\_REQUEST Copy Conclusion Following this guide, you have successfully set up a GraphQL API with the help of AWS AppSync and managed to deploy it utilizing Serverless Framework. You’ve learned how to add and connect data sources, write resolvers, and carry out the testing of your API. With this configuration, it is possible to create highly flexible and scalable APIs that are capable of complex query resolution. AWS AppSync and the Serverless Framework work together to provide a strong toolkit for building modern apps, facilitating real-time data handling, and simplifying development.

**Ebrahim Ali**29 Oct 2024 Read →

[![Secure your GraphQL API with some advanced strategies](https://www.craftsmensoftware.com/hubfs/Secure%20your%20GraphQL%20with%20some%20advanced.webp)](https://www.craftsmensoftware.com/blog/secure-your-graphql-api-with-some-advanced-strategies)

### [Secure your GraphQL API with some advanced strategies](https://www.craftsmensoftware.com/blog/secure-your-graphql-api-with-some-advanced-strategies)

Are you ready to learn how to become a superhero in the world of GraphQL? By giving clients superpowers, GraphQL opens up a world of possibilities, but as Uncle Ben famously said, “with great power comes great responsibility.” In the next few sections, we’ll dive into some strategies that will help you secure your GQL server from any nefarious queries lurking in the shadows. It’s time to don your cape and protect your GraphQL endpoint like the true hero you are! What is GraphQL? GraphQL is a query language for APIs (although often confused with being a database technology) that was developed by Facebook in 2012 and was open-sourced three years later. It is a powerful alternative to REST APIs and enables more efficient and flexible data fetching. In essence, GraphQL is designed to allow clients to specify exactly what data they need and receive only that data in response. This is one of the key advantages of GraphQL which in contrast to traditional REST APIs, where clients often receive more data than they need (Overfetching) and have to make multiple requests to get all the necessary information (Underfetching). Suppose we have a car cyclopedia platform with the following REST API endpoints: GET /cars GET /cars/{id} GET /cars/{id}/parts GET /manufacturers/{id} GET /manufacturers/{id}/cars Copy   To retrieve a car and its parts, we need to make multiple requests to different endpoints. For example, to retrieve the car with ID#123 and its parts, we would need to make the following requests: Copy   With GraphQL, clients can specify the shape of the data they need using a hierarchical structure, which is called a query. Here’s an example of a GraphQL query to retrieve the car with ID 123 and its parts, along with the manufacturers who made the car: query { cars (id: "123") { id model price manufacturers { id name } parts { id model manufacturers { id name } } } } Copy   This query specifies the exact data we want to retrieve and its structure. The response will only include the requested data, which can improve performance and reduce network usage. Additionally, we can retrieve data from multiple resources in a single request, which can simplify our code and reduce the number of API calls we need to make. Seems Great! But why do we need extra security? Already you may have got the idea that GraphQL gives enormous power to clients (It’s Over 9000!!!). Because clients can create extremely complicated queries, our servers need to be ready to handle them. Besides, these requests may be malicious ones coming from bad clients, or they could just be very big ones coming from good clients that could potentially take our GraphQL server down. So, it is our responsibility to impose some strategies to avoid these risks. Timeout Most of the time we just use the simplest one which is a timeout and call it a day. But for GraphQL, setting the optimal timeout is very tough as a legitimate complex query may take more than the time allowed, which may result in strange behaviors. Also, damage can already be done even before the timeout halts the execution. So, what we can do is to use this as a final protection and apply some advanced strategies beforehand. Maximum Query Depth GraphQL provides a strongly typed schema that allows for validation and documentation of the API. As we covered earlier, clients using GraphQL may craft any complex query they want. Since GraphQL schemas are often cyclic graphs, this means a client could craft a query like this one: query IhaveComeToBargain { # depth: 0 bargainer (id: "strange") { # depth: 1 dormammu { # depth: 2 bargainer { # depth: 3 dormammu { # depth: 4 bargainer { # depth: 5 dormammu { # depth: 6 bargainer { # depth: 7 # You cannot do this forever . . . # Actually I (client) can!!! } } } } } } } } Copy   In the above example, the query has a depth of possibly more than 7. If we know our schema well, we can have an idea of how deep a legit query can go and set a Maximum Query Depth threshold for the client. The GraphQL server then can reject or accept a request based on its depth by analyzing the query document’s abstract syntax tree (AST). Query Complexity Sometimes, depth alone cannot force all abusive queries. For example, a query requesting an enormous number of nodes on the root will be very expensive but unlikely to be blocked by a query depth analyzer. Some fields in our schema could be more complex to compute than others. To calculate how complex the query is let us give each field a complexity of 1. Then take a look at this example: query { car (id: "123") { # complexity: 1 manufacturer { # complexity: 1 name # complexity: 1 } } } But what if we wanted more cars produced by the manufacturer of car#123? So, we should consider arguments also when calculating complexity. query { car (id: "123") { # complexity: 1 manufacturer { # complexity: 1 name # complexity: 1 cars (first: 100) { # complexity: 100 model # complexity: 1 } } } } Copy   Throttling The above solutions are great when we want to stop clients who are making large queries. But what if the client is trying to abuse our server with a lot of medium sized queries? In REST APIs, a simple throttle is enough to stop clients from requesting resources too often. In GraphQL just throttling on the number of requests won’t help us. Also, the server has no idea about the number of requests that are acceptable, because that is actually defined by clients. Throttling Based on Server Time We can estimate how expensive a query is based on the server time it needs to execute. Then we can deduce maximum server time a client can use over a certain time delta. After we can decide how much time should be added to a client over time, we can implement the leaky bucket throttling algorithm. Leaky Bucket Suppose we give our maximum server time (Bucket Size) allowed to 2000ms; clients get 200ms of server time per second (Leak rate). If a single query takes 500ms to complete, the client can call this query 2000ms/500ms = 4 times. After that, any more execution would be blocked until more server time is added. After 3 seconds, bucket size will fill up to 600ms and the query can be executed one more time. Throttling Based on Query Complexity Throttling based on time is good because clients can now call complex queries less often as it takes more time to compute and call simple queries more as they take less time to finish. But the problem is we need to inform clients of these constraints so that they can configure themselves accordingly. But server time is not easy to explain to clients as the client doesn’t know how much time a query can take without trying them first, requiring trial and error. Also, the server might have other side effects running which could slow the query execution time. The GitHub public API uses some interesting strategies to throttle their clients. They impose 2 limits (Node limit and Rate limit) to protect their APIs. In Node limit, Node calculations are done exactly the way we saw earlier in the Query Complexity section. In the Rate limit they calculate based on the number of requests a query has to fulfill. But we know a single GraphQL query makes a single request to the server. How does that even work!? Using their strategy in our cars example will make things a bit easier to understand. query { manufacturer (first: 50) { # complexity: 50 name # complexity: 1 cars (first: 100) { # complexity: 100 model # complexity: 1 parts (last: 20) { # complexity: 20 model # complexity: 1 manufacturer (first: 10) { # complexity: 10 model # complexity: 1 } } } } } Copy   Here we need to add up the number of requests needed to fulfill each unique connection in the call. We are actually calling it a request each time we want to connect to a unique list to get its items. Each new connection can also have its own point value. This is because you can have multiple systems(database, legacy or third—party systems) behind a single, coherent GraphQL API. So, each connection can have a different load on the server. But for simplicity, we are giving fixed 1 point to each connection here. First, we are getting the first 50 manufacturers from the list. Although the complexity is 50, the API has to connect to the manufacturers list once. So, total requests = 1. Then, we are getting 100 cars made by the manufacturers which we got from each of the 50 manufacturers. So, total requests = 50. Then, we are returning 20 parts from each of the probable 100 cars x 50 manufacturers = 5000 cars. So, total requests = 5000 If we dive more, we are getting 10 manufacturers from each of the potential 5000 cars x 20 parts = 100,000 parts. So, total requests = 100,000 Total = 100,000 + 5000 + 50 + 1 = 105051 As the number can get even bigger in the real world, we can normalize the number by dividing it by 100 to get the final aggregate cost. In our example, we get a final score of around 1051. Then we can set the optimized bucket size and leak rate accordingly and express them to the clients. That’s it! We have discussed some of the approaches to secure our GraphQL server against unexpected queries. You can also use data loaders and implement caching to minimize the number of requests to backing data sources even more. But we need to keep in mind that none of the approaches can solve world hunger alone. So, we should know their limits and decide accordingly.

**Arafat Ibne Yousuf**05 Jan 2020 Read →

## Looking for A Trusted AI-native Partner?

Our engineers work inside your product team, bringing broadcast experience and AI-native workflows. Let’s talk about your platform, your roadmap and where you need support.

[Book a Strategy Call →](https://www.craftsmensoftware.com/contact-us)

[![Mahmudul Haque Azad](https://www.craftsmensoftware.com/hs-fs/hubfs/Azad_bhai_new_DP__grey_BG.png?width=58&height=58&name=Azad_bhai_new_DP__grey_BG.png) Book Free 1:1 with Mahmudul Haque Azad CEO & Janitor, Craftsmen](https://www.craftsmensoftware.com/contact-us)

![](https://www.craftsmensoftware.com/hs-fs/hubfs/Azad_bhai_new_DP__grey_BG.png?width=46&height=46&name=Azad_bhai_new_DP__grey_BG.png)

Book Free 1:1 with Mahmudul Haque Azad

CEO & Janitor, Craftsmen

Loading calendar…

### ABOUT CRAFTSMEN

The Team[Our Partnership Model](https://www.craftsmensoftware.com/how-we-work)[Client Stories](https://www.craftsmensoftware.com/client-success-stories)[Career](https://careers.craftsmensoftware.com/)[FAQ](https://www.craftsmensoftware.com/frequently-asked-questions-faq)[Privacy Policy](https://www.craftsmensoftware.com/privacy-policy)

<https://www.linkedin.com/company/craftsmensoftware/><https://www.youtube.com/@craftsmensoftware>

### HEADQUARTERS

Craftsmen UK

One Sovereign Quay, Bridge End, Leeds, West Yorkshire LS1 4AG, United Kingdom

### OPERATIONAL HUB

Craftsmen Bangladesh

Plot # 316, Lane # 4, DOHS Baridhara, Dhaka 1206, Bangladesh

### SALES & PARTNERSHIP

Craftsmen Norway

Kong Oscars gate 66, 68, 5017 Bergen, Norway

Craftsmen France

6 Avenue Pierre Grenier, 92100 Boulogne-Billancourt, Paris, France

### A TEAM YOU CAN TRUST

[![ISO 9001 certified](https://crafty-astro-2-0.skarif2.workers.dev/_astro/iso-9001.rB3N1YoH_19riAQ.webp)](https://www.craftsmensoftware.com/trust-centre)[![ISO 27001 certified](https://crafty-astro-2-0.skarif2.workers.dev/_astro/iso-27001.Ds31wC1E_Z2lNtpQ.webp)](https://www.craftsmensoftware.com/trust-centre)[![ISO 27701 certified](https://crafty-astro-2-0.skarif2.workers.dev/_astro/iso-27701.qBI_Bjkt_Z1J5MRi.webp)](https://www.craftsmensoftware.com/trust-centre)

[![Glassdoor reviews](https://crafty-astro-2-0.skarif2.workers.dev/_astro/glassdoor.C76Qo6k3_Z1Br5vs.webp)](https://www.glassdoor.com/Overview/Working-at-Craftsmen-EI_IE3004266.11,20.htm)[![GoodFirms, top software development company in Bangladesh](https://crafty-astro-2-0.skarif2.workers.dev/_astro/goodfirms.CJaHzqAg_1xfRU9.webp)](https://www.craftsmensoftware.com/blog/craftsmen-thrives-at-goodfirms-by-offering-scalable-robust-software-solutions-developed-with-quality-by-maestros)

© 2026 Craftsmen. All rights reserved.

```json
{
  "@context" : "https://schema.org",
  "@type" : "SoftwareCompany",
  "address" : [ {
    "@type" : "PostalAddress",
    "addressCountry" : "Norway",
    "addressLocality" : "Oslo"
  }, {
    "@type" : "PostalAddress",
    "addressCountry" : "United Kingdom",
    "addressLocality" : "London"
  }, {
    "@type" : "PostalAddress",
    "addressCountry" : "France",
    "addressLocality" : "Paris"
  }, {
    "@type" : "PostalAddress",
    "addressCountry" : "United States",
    "addressLocality" : "New York"
  }, {
    "@type" : "PostalAddress",
    "addressCountry" : "Bangladesh",
    "addressLocality" : "Dhaka"
  } ],
  "areaServed" : [ {
    "@type" : "Country",
    "name" : "Norway"
  }, {
    "@type" : "Country",
    "name" : "Sweden"
  }, {
    "@type" : "Country",
    "name" : "United Kingdom"
  }, {
    "@type" : "Country",
    "name" : "France"
  }, {
    "@type" : "Country",
    "name" : "United States"
  }, {
    "@type" : "Country",
    "name" : "Bangladesh"
  } ],
  "description" : "Trusted AI-native engineering partner providing software team extension, IT staff augmentation, and dedicated developer teams globally.",
  "logo" : "https://www.craftsmensoftware.com/hubfs/logo.png",
  "name" : "Craftsmen Software",
  "url" : "https://www.craftsmensoftware.com"
}
```