This week, I’ve been given the important task of finding the bottleneck in a new graphql application that will be launching soon. Load testing isn’t something new to me, so I got to work. I started firing up requests using Apache Bench, but was unable to get a single request to not return a 5xx error.

$ ab -n 10 -c 1 -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept: application/json' -H 'Origin: https://REDACTED' 'https://REDACTED/graphql'
This is ApacheBench, Version 2.3 <$Revision: 1757674 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking REDACTED (be patient).....done
Server Software:
Server Hostname:        REDACTED
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128
TLS Server Name:        REDACTED
Document Path:          /graphql
Document Length:        18 bytes
Concurrency Level:      1
Time taken for tests:   0.156 seconds
Complete requests:      10
Failed requests:        0
Non-2xx responses:      10			<-- All the requests failed
Total transferred:      2590 bytes
HTML transferred:       180 bytes
Requests per second:    63.93 [#/sec] (mean)
Time per request:       15.642 [ms] (mean)
Time per request:       15.642 [ms] (mean, across all concurrent requests)
Transfer rate:          16.17 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        5    6   0.3      6       6
Processing:     5   10   9.4      7      36
Waiting:        5   10   9.4      7      36
Total:         11   16   9.5     14      42
Percentage of the requests served within a certain time (ms)
  50%     14
  66%     14
  75%     14
  80%     17
  90%     42
  95%     42
  98%     42
  99%     42
 100%     42 (longest request)

Note: You can tell all the requests failed via the line Non-2xx responses: 10

I was able to properly curl the service, but was unable to hit it with postman or ab.

$ curl 'https://<REDACTED>/graphql' -H 'Accept-Encoding: gzip, deflate, br' \
-H 'Content-Type: application/json' -H 'Accept: application/json' \
-H 'Connection: keep-alive' -H 'DNT: 1' -H 'Origin: REDACTED' \
--data-binary '{"query":"{getImage(data: {id: \"REDACTED\"}){\n  image{createdAt, source, link, id, width, md5}\n}} "}' --compressed
{"data":{"getImage":{"image":{"createdAt":"1304972624","source":null,"link":null,"id":"REDACTED","width":900,"md5":"REDACTED"}}}}

Taking a look again, I realized that I was incorrectly incorrectly passing the graphql query. Instead of passing it as a header, you need to pass it using the -p flag.

$ cat post.txt
{"query":"GRAPHQL QUERY"}
$ ab -n 2000 -c 100 -H 'Accept-Encoding: gzip, deflate, br' -H \
 'Accept-Encoding: gzip, deflate, br' \
 -H 'Accept: application/json' -H 'Origin: https://REDACTED' -T 'application/json' \
 -p post.txt 'https://REDACTED/graphql'