{"id":37150062,"url":"https://github.com/domsolutions/gopayloader","last_synced_at":"2026-01-14T17:43:26.029Z","repository":{"id":157321052,"uuid":"628227758","full_name":"domsolutions/gopayloader","owner":"domsolutions","description":"HTTP/S benchmark/load testing cross-platform tool with optional jwt generation - supports HTTP/1.1, HTTP/2, HTTP/3","archived":false,"fork":false,"pushed_at":"2025-02-01T17:58:03.000Z","size":337,"stargazers_count":18,"open_issues_count":6,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-01T18:37:52.380Z","etag":null,"topics":["benchmark","benchmark-framework","benchmark-scripts","benchmarking","fasthttpclient","go","golang","high-performance","http-client","http-requests","http2","http3","http3-client","jwt","jwt-authentication","load-testing","rps"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/domsolutions.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-15T09:45:59.000Z","updated_at":"2025-02-01T17:56:56.000Z","dependencies_parsed_at":"2024-01-12T10:25:22.078Z","dependency_job_id":"996b8bf8-90e7-467b-b29e-ba62ce37877c","html_url":"https://github.com/domsolutions/gopayloader","commit_stats":{"total_commits":134,"total_committers":4,"mean_commits":33.5,"dds":"0.35820895522388063","last_synced_commit":"daf5135749cb4d2891e74c4c61e8977699351b03"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/domsolutions/gopayloader","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/domsolutions%2Fgopayloader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/domsolutions%2Fgopayloader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/domsolutions%2Fgopayloader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/domsolutions%2Fgopayloader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/domsolutions","download_url":"https://codeload.github.com/domsolutions/gopayloader/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/domsolutions%2Fgopayloader/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28428927,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T16:38:47.836Z","status":"ssl_error","status_checked_at":"2026-01-14T16:34:59.695Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["benchmark","benchmark-framework","benchmark-scripts","benchmarking","fasthttpclient","go","golang","high-performance","http-client","http-requests","http2","http3","http3-client","jwt","jwt-authentication","load-testing","rps"],"created_at":"2026-01-14T17:43:25.288Z","updated_at":"2026-01-14T17:43:26.019Z","avatar_url":"https://github.com/domsolutions.png","language":"Go","readme":"# Gopayloader\n\n[![Build status](https://github.com/domsolutions/gopayloader/actions/workflows/go.yml/badge.svg)](https://github.com/domsolutions/gopayloader/actions/workflows/go.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/domsolutions/gopayloader)](https://goreportcard.com/report/github.com/domsolutions/gopayloader)\n[![GoDoc](https://godoc.org/github.com/domsolutions/gopayloader?status.svg)](http://godoc.org/github.com/domsolutions/gopayloader)\n\nGopayloader is an HTTP/S benchmarking tool. Inspired by [bombardier](https://github.com/codesenberg/bombardier/) it also uses [fasthttp](https://github.com/valyala/fasthttp) which allows for fast creation and sending of requests due to low allocations and lots of other improvements.\nIt uses this client by default, a different client can be used with `--client` flag.\n\nSupports all HTTP versions, using [quic-go](https://github.com/quic-go/quic-go) for HTTP/3 client with `--client nethttp3`. For HTTP/2 can use  with `--client nethttp2`. By default uses fasthttp HTTP/1.1 client.\n\nSupports ability to generate custom JWTs to send in headers with payload (only limited by HDD size). This can be useful if the service being\ntested is JWT authenticated. Each JWT generated will be unique as contains a unique `jti` in claims i.e.\n\n```json\n{\n  \"jti\": \"8f2d1472-084c-4662-ae74-04e0f1de4993\"\n}\n```\n\nA private key is supplied as a flag with optional flags to set other standard claims i.e. `sub` `aud`, `iss` and can also provide custom claims. It will then check if the required number of jwts has already\nbeen generated in a previous test by checking a file on disk. All JWTs are saved on disk in cache, this allows\nhuge number of jwts to be generated without affecting in-memory use of gopayloader. Once all jwts have been generated\nthe tests begin, and jwts are streamed from disk to requests. This keeps the memory footprint low. The other major benefit to pre-generating\nis all of CPU cycles can be dedicated to sending the requests thus achieving higher RPS.\n\n## Contributing\n\nContributions are welcome, please read the guidelines [here.](./CONTRIBUTING.md)\n\n## Installation\n\nCan install with (supported go versions \u003e= `1.23`)\n\n```shell\ngo install github.com/domsolutions/gopayloader@latest \n```\n\nOr download pre-compiled binaries from [releases](https://github.com/domsolutions/gopayloader/releases)\n\n## Benchmark comparisons\n\nAll tests are running against below HTTP/1.1 server;\n\n```shell\n./gopayloader http-server -p 8081 -s 1 --fasthttp-1\n```\n\nTested running for `30 seconds` reqs over `125` connections\n\nGopayloader tested with\n```shell\n./gopayloader run http://localhost:8081 -c 125 --time 30s \n```\n\nachieved mean RPS of **53,098**\n\n| Tool                                                     | Cmd                                                      | Mean RPS | Gopayloader improvement               |\n|----------------------------------------------------------|----------------------------------------------------------|----------|---------------------------------------|\n| [k6](https://github.com/grafana/k6)                      | `k6 run --vus 125 --duration 30s k6.js`                  | 15,268   | \u003cspan style=\"color:green\"\u003e235%\u003c/span\u003e |\n| [hey](https://github.com/rakyll/hey)                     | `hey -z 30s -c 125 http://localhost:8081`                | 22,644   | \u003cspan style=\"color:green\"\u003e134%\u003c/span\u003e |\n| [bombardier](https://github.com/codesenberg/bombardier/) | `bombardier http://localhost:8081 -c 125 --duration=30s` | 51,311   | \u003cspan style=\"color:green\"\u003e3.4%\u003c/span\u003e |\n\n\n## Usage\n\nTo list all available flags run;\n\n```shell\nLoad test HTTP/S server - supports HTTP/1.1 HTTP/2 HTTP/3\n\nUsage:\n  gopayloader run \u003chost\u003e(host format - protocol://host:port/path i.e. https://localhost:443/some-path) [flags]\n\nFlags:\n  -b, --body string              request body\n      --body-file string         read request body from file\n      --client string            fasthttp for fast http/1.1 requests\n                                 nethttp for standard net/http requests using http/1.1\n                                 nethttp2 for standard net/http requests using http/2\n                                 nethttp3 for standard net/http requests supporting http/3 using quic-go (default \"fasthttp\")\n  -c, --connections uint         Number of simultaneous connections (default 1)\n  -k, --disable-keep-alive       Disable keep-alive connections\n  -H, --headers strings          headers to send in request, can have multiple i.e -H 'content-type:application/json' -H' connection:close'\n  -h, --help                     help for run\n      --jwt-aud string           JWT audience (aud) claim\n      --jwt-claims string        JWT custom claims\n      --jwt-header string        JWT header field name\n      --jwt-iss string           JWT issuer (iss) claim\n      --jwt-key string           JWT signing private key path\n      --jwt-kid string           JWT KID\n      --jwt-sub string           JWT subject (sub) claim\n  -f, --jwts-filename string     File path for pre-generated JWTs, separated by new lines\n  -m, --method string            request method (default \"GET\")\n      --mtls-cert string         mTLS cert path\n      --mtls-key string          mTLS cert private key path\n      --parallel                 Sends reqs in parallel per connection with HTTP/2 or HTTP/3\n      --read-timeout duration    Read timeout (default 5s)\n  -r, --requests int             Number of requests\n      --skip-verify              Skip verify SSL cert signer\n      --ticker duration          How often to print results while running in verbose mode (default 1s)\n  -t, --time duration            Execution time window, if used with -r will uniformly distribute reqs within time window, without -r reqs are unlimited\n  -v, --verbose                  verbose - slows down RPS slightly for long running tests\n      --write-timeout duration   Write timeout (default 5s)\n\n```\n\nBy default, it runs in quiet mode to dedicate all CPU cycles to sending requests to achieve max RPS. Verbose\nmode can be enabled with `-v` flag.\n\nTo run `1000000` requests across `150` connections;\n\n```shell\n./gopayloader run http://localhost:8081 -c 150 -r 1000000 \n\nGopayloader v0.1.0 HTTP/JWT authentication benchmark tool \nhttps://github.com/domsolutions/gopayloader\n\n INFO  Running 1,000,000 request/s with 150 connection/s against http://localhost:8081\n SUCCESS  Payload complete, calculating results\n SUCCESS  Gopayloader results \n\n+-----------------------+-------------------------------+\n| METRIC                | RESULT                        |\n+-----------------------+-------------------------------+\n| Total time            | 18.983561852s                 |\n| Start time            | Thu, 27 Apr 2023 12:04:47 BST |\n| End time              | Thu, 27 Apr 2023 12:05:06 BST |\n| Completed requests    | 1000000                       |\n| Failed requests       | 0                             |\n+-----------------------+-------------------------------+\n| Average RPS           | 52677.153                     |\n| Max RPS               | 54411                         |\n| Min RPS               | 47096                         |\n+-----------------------+-------------------------------+\n| Req size (bytes)      | 42                            |\n| Req size/second (MB)  | 2.225                         |\n| Req total size (MB)   | 40.054                        |\n+-----------------------+-------------------------------+\n| Resp size (bytes)     | 135                           |\n| Resp size/second (MB) | 7.153                         |\n| Resp total size (MB)  | 128.746                       |\n+-----------------------+-------------------------------+\n| Average latency       | 2.816219ms                    |\n| Max latency           | 62.938092ms                   |\n| Min latency           | 74.879µs                      |\n+-----------------------+-------------------------------+\n| Response code; 200    | 1000000                       |\n+-----------------------+-------------------------------+\n```\n\nTo run `1000000` requests across `150` connections with jwts (jwts will only be generated when number of requests are specified);\n\nExample header jwt generated;\n\n```json\n{\n  \"alg\": \"ES256\",\n  \"kid\": \"3434645743124\",\n  \"typ\": \"JWT\"\n}\n```\n\nexample body;\n\n```json\n{\n  \"aud\": \"some-audience\",\n  \"exp\": 1714130039,\n  \"iss\": \"some-issuer\",\n  \"jti\": \"05181473-bbd6-4d21-8942-d86c2e972b2b\",\n  \"sub\": \"my-subject\",\n  \"iat\": 1719410063,\n  \"browser\": \"chrome\"\n}\n```\n\nNote `jti` will be different for each jwt.\n\nWill set jwt value = header field `my-jwt` and sign with key `./private-key.pem` and KID `3434645743124`\n\n`./gopayloader run http://localhost:8081 -c 150 -r 1000000 --jwt-header \"my-jwt\" --jwt-key ./private-key.pem --jwt-kid 3434645743124 --jwt-sub \"my-subject\" --jwt-aud \"some-audience\" --jwt-iss \"some-issuer\" --jwt-claims \"{\\\"iat\\\": 1719410063, \\\"browser\\\": \\\"chrome\\\"}\"`\n\n```shell\nGopayloader v0.1.0 HTTP/JWT authentication benchmark tool \nhttps://github.com/domsolutions/gopayloader\n\n INFO  Sending jwts with requests, checking for jwts in cache\n INFO  Generating batch of 1000000 JWTs and saving to disk\n INFO  Running 1,000,000 request/s with 150 connection/s against http://localhost:8081\n SUCCESS  Payload complete, calculating results\n SUCCESS  Gopayloader results \n\n+-----------------------+-------------------------------+\n| METRIC                | RESULT                        |\n+-----------------------+-------------------------------+\n| Total time            | 19.679817482s                 |\n| Start time            | Thu, 27 Apr 2023 12:14:48 BST |\n| End time              | Thu, 27 Apr 2023 12:15:08 BST |\n| Completed requests    | 1000000                       |\n| Failed requests       | 0                             |\n+-----------------------+-------------------------------+\n| Average RPS           | 50813.479                     |\n| Max RPS               | 52708                         |\n| Min RPS               | 48098                         |\n+-----------------------+-------------------------------+\n| Req size (bytes)      | 370                           |\n| Req size/second (MB)  | 18.572                        |\n| Req total size (MB)   | 352.859                       |\n+-----------------------+-------------------------------+\n| Resp size (bytes)     | 135                           |\n| Resp size/second (MB) | 6.776                         |\n| Resp total size (MB)  | 128.746                       |\n+-----------------------+-------------------------------+\n| Average latency       | 2.92205ms                     |\n| Max latency           | 78.047387ms                   |\n| Min latency           | 80.768µs                      |\n+-----------------------+-------------------------------+\n| Response code; 200    | 1000000                       |\n+-----------------------+-------------------------------+\n```\n\nIf you have your own JWTs you want to test, you can supply a file to send the JWTs i.e. `./my-jwts.txt` where each jwt is separated by a new line.\n\n```shell\n./gopayloader run http://localhost:8081 -c 1 -r 1000000 --jwt-header \"my-jwt\" -f ./my-jwts.txt\n```\n\n\nTo remove all generated jwts;\n\n```shell\n./gopayloader clear-cache \n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdomsolutions%2Fgopayloader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdomsolutions%2Fgopayloader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdomsolutions%2Fgopayloader/lists"}