Thursday, June 9, 2022
HomeWordPress DevelopmentLoad Testing GraphQL Efficiency With k6 and StepZen

Load Testing GraphQL Efficiency With k6 and StepZen


For a lot of corporations, efficiency is the principle motive to go together with GraphQL. However is {that a} legitimate argument? Typically builders evaluate GraphQL to REST APIs and see the N+1 requests (or over-fetching) as an essential motive to decide on GraphQL. Let’s put that to the take a look at and discover if GraphQL APIs can outperform present REST APIs. For this, we’ll take two GraphQL-ized REST APIs (IP-API and Frankfurter) and cargo take a look at the efficiency of GraphQL, nested information in GraphQL, and evaluate it with the unique REST APIs. We’ll be utilizing the device k6, one of the crucial widespread load testing instruments right this moment, to do that efficiency take a look at.



Discover a GraphQL API

Let’s discover a StepZen GraphQL API transformed from a REST API. On this case, I’ve used the StepZen CLI to transform the IP-API REST API to GraphQL, utilizing the directions from the docs. This free REST API helps you to seek for a location based mostly on its IP tackle. We GraphQL-ized the IP-API REST API with StepZen and explored it with GraphiQL. The GraphiQL interface might be discovered right here and appears like the next:

IP-API in GraphiQL

You may see the question you are sending to the GraphQL API on the left-hand facet of the display, whereas the right-hand facet reveals the response. It’s named GetLocation. Naming queries is really helpful because it helps GraphQL APIs with, for instance, caching. Additionally, word that the response has the identical form because the question you requested.

After exploring this GraphQL API, let’s arrange k6 so we are able to use it to check GraphQL within the subsequent part.



Utilizing k6 for GraphQL

To load take a look at this GraphQL API, we’ll be utilizing k6, an open-source load testing device. You may run k6 in your native machine by putting in it from the GitHub repository or utilizing k6’s cloud providing. Utilizing this device, you possibly can take a look at any API that accepts HTTP requests. Probably the most simple take a look at you possibly can run makes use of the http.submit operate from k6:

import http from 'k6/http';

const question = `
  question GetLocation {
    ipApi_location(ip: “8.8.8.8”) {
      id
      metropolis
      nation
    }
  }
`;

const headers = {
  'Content material-Sort': 'utility/json',
};

export default operate () {
  http.submit(
    'https://graphqldd.stepzen.web/api/dd1cf47f51ac830fe21dc00ec80cee65/__graphql',
    JSON.stringify({ question }),
    { headers },
  );
}
Enter fullscreen mode

Exit fullscreen mode

This k6 script can now hit the GraphQL API utilizing the question to load take a look at its efficiency. As a result of the IP tackle is static, k6 will make the identical request repeatedly in your efficiency take a look at. Moreover, because the GraphQL API will cache the outcomes, the assessments will get much less reasonable as totally different customers will use totally different IP addresses when hitting the GraphQL API. Due to this fact it’s best to make use of dynamic variables in your GraphQL question. The identical question with a dynamic worth for ip will seem like this:

question GetLocation($ip: String!) {
  ipApi_location(ip: $ip) {
    ip
    metropolis
    nation
  }
}
Enter fullscreen mode

Exit fullscreen mode

When sending the request, you’ll want to append a JSON object containing a price for ip alongside your GraphQL question. For those who go to the GraphiQL interface, you should use the tab “question parameters” for this:

Query with dynamic paraamters in GraphiQL

Utilizing the dynamic question parameters, you might use the http.batch operate from k6 to ship a number of requests with totally different values for ip to the GraphLQ API to simulate a extra reasonable testing situation:

import http from 'k6/http';

const question = `
  question GetLocation($ip: String!) {
    ipApi_location(ip: $ip) {
      ip
      metropolis
      nation
    }
  }
`;


const headers = {
  'Content material-Sort': 'utility/json',
};


export default operate () {
  http.batch([
    [
      'POST',
      'https://graphqldd.stepzen.net/api/dd1cf47f51ac830fe21dc00ec80cee65/__graphql',
      JSON.stringify({ query, variables: { ip: '8.8.8.8' } }),
      { headers },
    ],
    [
      'POST',
      'https://graphqldd.stepzen.net/api/dd1cf47f51ac830fe21dc00ec80cee65/__graphql',
      JSON.stringify({ query, variables: { ip: '12.0.1.3' } }),
      { headers },
    ],
    [
      'POST',
      'https://graphqldd.stepzen.net/api/dd1cf47f51ac830fe21dc00ec80cee65/__graphql',
      JSON.stringify({ query, variables: { ip: '95.120.0.0' } }),
      { headers },
    ],
  ]);
}
Enter fullscreen mode

Exit fullscreen mode

Working this k6 script will ship a batch of requests to the GraphQL API with totally different IP addresses. These requests are despatched in parallel, supplying you with a extra reasonable situation than sending only one. You would additionally create an array of IP addresses and loop over this to create a brand new array that you just move to the http.batch operate. The subsequent part will use these scripts to efficiency take a look at this GraphQL API with k6.



Load testing a GraphQL Question

With the k6 scripts arrange, we are able to now do a efficiency take a look at on the GraphQL API. We will run two assessments, one with a static IP tackle and one other with batched requests and dynamic IP addresses. Working these assessments solely requires you to have k6 downloaded and put in in your native machine, or it’s best to have a k6 cloud account.

To run the primary take a look at, you’ll want to save the script in a file referred to as easy.js so you possibly can run the take a look at with:

k6 run --vus 10 --duration 30s easy.js
Enter fullscreen mode

Exit fullscreen mode

This command runs k6 with 10 VUs (Digital Customers) for 30 seconds. To get extra info on working k6 go right here.

Load testing results k6

The outcomes present that the GraphQL API was hit nearly 2500 instances in 30 seconds, with a mean length of 122ms. Which may be very near the common length of the hits for 95% of all requests that means there aren’t any outliers.

By wanting on the outcomes, we are able to additionally take a look at the scalability of the GraphQL API that runs on StepZen. Due to this fact we have to have a more in-depth have a look at the variety of iterations that the GraphQL API dealt with:

iterations.....................: 2472 82.082529/s
Enter fullscreen mode

Exit fullscreen mode

After we ran the k6 script for 30 seconds with ten concurrent VUs, you possibly can see that k6 hit the GraphQL API nearly 2500 instances – or 82 instances per second. If the GraphQL API is completely scalable, it ought to be capable of deal with ten instances extra iterations after we enhance the variety of concurrent VUs to 100. Let’s do that out:

k6 run --vus 100 --duration 30s easy.js
Enter fullscreen mode

Exit fullscreen mode

This ends in the next:

Load testing results k6

As anticipated for a superbly scalable service, the variety of iterations is not 820 however 798, which is just a 3% distinction. The GraphQL API is not completely scalable however is getting fairly near being so.

Subsequent to testing the easy question with a static IP tackle, we are able to additionally run the script with the dynamic IP tackle by putting it in a file referred to as batch.js:

k6 run --vus 10 --duration 30s batch.js
Enter fullscreen mode

Exit fullscreen mode

The iterations to the GraphQL API on this take a look at are despatched in batch, that means that each iteration ends in three HTTP requests – the variety of requests added to the http.batch operate. As we realized beforehand, the GraphQL API is nearly completely scalable.

The variety of iterations the GraphQL API can deal with on this take a look at ought to be roughly the identical, whereas the variety of HTTP requests ought to be round thrice bigger. Once I ran the take a look at, the variety of iterations resulted in:

http_reqs......................: 7251   240.737555/s
iteration_duration.............: avg=124.43ms min=116.53ms med=121.91ms max=509.1ms  p(90)=126.39ms p(95)=129.13ms
iterations.....................: 2417   80.245852/s
Enter fullscreen mode

Exit fullscreen mode

With 2417 versus 2500 requests, the variety of iterations is comparable, and the variety of HTTP requests is thrice bigger than the variety of iterations.

Now we all know k6 can take a look at the efficiency of GraphQL APIs and the GraphQL API is scalable. Let’s proceed by testing a heavier GraphQL question within the subsequent part.



Load testing totally different information sources

The power to find out the form of the information is not the one motive builders undertake GraphQL because the question language for his or her APIs. GraphQL APIs have only one endpoint, and the queries (or different operations) may deal with nested information. You may request information from totally different database tables (like with SQL joins) and even varied information sources in a single request. That is totally different from REST APIs, the place you usually should hit a number of endpoints to get information from different sources.

Within the GraphiQL interface for the StepZen GraphQL API we’re testing, you possibly can discover what different queries can be found. A type of queries will get information from the Frankfurter REST API, an open-source API containing present and historic change fee information revealed by the European Central Financial institution. This REST API is transformed to GraphQL utilizing StepZen in the identical approach because the IP-API was. To get the present conversion fee from Euros to US {Dollars}, you possibly can question:

question GetConversion {
  frankfurter_latest_rates(from: "EUR", to: "USD") {
    amoun
    base
    date
    charges
  }
}
Enter fullscreen mode

Exit fullscreen mode

The question above will get the dialog fee from 1 EUR to USD on the present date. As a result of the schema for this API is a mixture of the information from IP-API and Frankfurter, there’s extra you are able to do. Utilizing this mix, you will get the present location based mostly on the IP tackle and convert the native foreign money of that location to USD. This foreign money conversion is out there on the sphere priceInCountry. You may see the end result by visiting the GraphiQL interface, or on this picture beneath:

Query different data sources with StepZen

Moreover the IP tackle location, this question additionally lets the GraphQL API convert Euros to the native foreign money of that location. On this case, it means changing Euros to {Dollars} once more.

To get this information, the GraphQL API will do the next:

  • Ship a request to the underlying IP-API REST API to get the placement and foreign money based mostly on the IP tackle;
  • Convert the foreign money of that location to Euros utilizing the Frankfurter REST API.

We will use this nested question in a k6 script to do one other efficiency take a look at of the GraphQL API. This question has a distinct depth than the question we have used within the earlier part, as the information is now nested because it comes from totally different sources. You may put the next k6 script in a brand new file referred to as nested.js:

import http from 'k6/http';

const question = `
  question GetConversion($ip: String!, $quantity: Float!, $from: String!) {
    ipApi_location(ip: $ip) {
      ip
      metropolis
      nation
      foreign money
      priceInCountry(quantity: $quantity, from: $from)
    }
  }
`;

const headers = {
  'Content material-Sort': 'utility/json',
};

export default operate () {
  http.submit(
    'https://graphqldd.stepzen.web/api/dd1cf47f51ac830fe21dc00ec80cee65/__graphql',
    JSON.stringify({
      question,
      variables: {
        quantity: 1,
        from: 'EUR',
        ip: '8.8.8.8',
      },
    }),
    { headers },
  );
}
Enter fullscreen mode

Exit fullscreen mode

And run it beneath the identical circumstances because the earlier assessments:

k6 run --vus 10 --duration 30s nested.js
Enter fullscreen mode

Exit fullscreen mode

The outcomes of this efficiency take a look at are just like the take a look at with the batched requests. The batching is not occurring within the k6 script however on the GraphQL API, which handles the 2 requests to the underlying REST APIs. Because the GraphQL API is constructed to be performant, the distinction between the preliminary question to get simply the placement of the IP tackle and this question to get each the IP tackle location and the foreign money conversion is minimal. One thing you possibly can verify within the output of the k6 load take a look at beneath:

Results for k6 load test query different data sources

The take a look at we have simply run reveals GraphQL is completely in a position to get your information from totally different sources multi functional request. Let’s break down the GraphQL question to the REST API requests they’re doing beneath the hood within the ultimate part to show this level.



Examine GraphQL to REST efficiency

You have already realized tips on how to efficiency take a look at GraphQL utilizing k6 and the way that differs from testing a REST API. The final GraphQL question we have examined is asking two totally different REST API endpoints. There are two eventualities we are able to attempt to evaluate GraphQL and REST efficiency. Both arrange two separate assessments to check the efficiency of the person REST endpoints towards their corresponding GraphQL queries or recreate the entire conduct of the GraphQL API by straight calling the 2 REST API endpoints from a k6 take a look at.

The latter is probably the most attention-grabbing to check, as each REST endpoints must return information for the GraphQL question to resolve. The GraphQL question conduct we’re testing is:

question GetConversion($ip: String!, $quantity: Float!, $from: String!) {
  ipApi_location(ip: $ip) {
    ip
    cit
    nation
    foreign money
    priceInCountry(quantity: $quantity, from: $from)
  }
}
Enter fullscreen mode

Exit fullscreen mode

This sends requests to the REST endpoints:

  • To get the placement and foreign money for IP tackle 8.8.8.8 from IP-API: http://ip-api.com/json/8.8.8.8?fields=metropolis,nation,foreign money
  • To transform the foreign money from the IP tackle location to Euros from Frankfurter: https://api.frankfurter.app/newest?quantity=1&from=EUR&to=USD

To check this utilizing k6 you’ll want to arrange the next script in a brand new file, let’s name it relaxation.js:

import http from 'k6/http';
import { verify } from 'k6';

const headers = {
  'Content material-Sort': 'utility/json',
};

export default operate () {
  const response = http.get(
    'http://ip-api.com/json/8.8.8.8?fields=metropolis,nation,foreign money',
    null,
    { headers },
  );

  verify(response, {
    'foreign money ought to be returned': (res) => res.json().foreign money === 'USD',
  });

  http.get(
    'https://api.frankfurter.app/newest?quantity=1&from=EUR&to=USD',
    null,
    { headers },
  );
}
Enter fullscreen mode

Exit fullscreen mode

Not solely will this k6 efficiency take a look at name the 2 REST endpoints. However in an actual situation, it might make no sense to achieve the second endpoint to transform the places’ foreign money to Euros if the primary request would not return the native foreign money of the IP tackle. Working the take a look at above with the identical situations as we did for the opposite assessments:

k6 run --vus 10 --duration 30s relaxation.js
Enter fullscreen mode

Exit fullscreen mode

Provides the next outcomes:

Results for k6 load test REST

The very first thing that stands out is that solely 50 iterations with two HTTP requests per iteration are full in 30 seconds. Solely 3 VUs have been in a position to ship requests in these assessments, and 20% of all requests have failed. In comparison with the GraphQL API, these take a look at outcomes are disappointing. The GraphQL-ized variations of the 2 REST APIs can deal with many extra requests and resolve them sooner. Why is that this? The GraphQL API created utilizing StepZen applies caching the place the REST API itself would not appear to use any caching in any respect. The requests to the IP-API endpoint appear to fail twenty % of the time. Moreover, the GraphQL API may even batch requests or optimize for N+1 requests when wanted. For instance, you’ll want to request the identical information from the foreign money REST API twice.



Conclusion

GraphQL utilization has been on the rise, particularly amongst front-end builders who desire a extra declarative solution to deal with information. On this submit, we have explored tips on how to efficiency take a look at a GraphQL API utilizing k6. This GraphQL API was created with StepZen by changing the open-source REST APIs from IP-API and Frankfurter. The take a look at outcomes confirmed the GraphQL API was near being completely scalable and performant in all eventualities. In distinction, the person REST API endpoints had vital efficiency points within the assessments. That is as a result of StepZen GraphQL API’s efficiency optimizations, comparable to caching. For an entire efficiency take a look at script for GraphQL, see the StepZen GraphQL Benchmark device in this repository.

Wish to be taught extra about StepZen? Attempt it out right here or ask any query on the Discord right here.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments