{"id":13651225,"url":"https://github.com/cloudposse-archives/load-testing","last_synced_at":"2025-06-30T20:04:48.449Z","repository":{"id":45575509,"uuid":"134269921","full_name":"cloudposse-archives/load-testing","owner":"cloudposse-archives","description":"A collection of best practices, workflows, scripts and scenarios that Cloud Posse uses for load and performance testing of websites and applications (in particular those deployed on Kubernetes clusters)","archived":false,"fork":false,"pushed_at":"2023-12-15T11:53:17.000Z","size":785,"stargazers_count":55,"open_issues_count":1,"forks_count":13,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-12T07:46:12.467Z","etag":null,"topics":["docker-compose","grafana","k6","load-testing","scale-testing","stress-testing"],"latest_commit_sha":null,"homepage":"https://cloudposse.com/accelerate","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloudposse-archives.png","metadata":{"funding":{"github":"cloudposse"},"files":{"readme":"README.md","changelog":null,"contributing":null,"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}},"created_at":"2018-05-21T13:02:31.000Z","updated_at":"2024-11-19T18:34:33.000Z","dependencies_parsed_at":"2023-12-17T08:11:52.505Z","dependency_job_id":null,"html_url":"https://github.com/cloudposse-archives/load-testing","commit_stats":null,"previous_names":["cloudposse-archives/load-testing","cloudposse/load-testing"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/cloudposse-archives/load-testing","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudposse-archives%2Fload-testing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudposse-archives%2Fload-testing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudposse-archives%2Fload-testing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudposse-archives%2Fload-testing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloudposse-archives","download_url":"https://codeload.github.com/cloudposse-archives/load-testing/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudposse-archives%2Fload-testing/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262842917,"owners_count":23373165,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["docker-compose","grafana","k6","load-testing","scale-testing","stress-testing"],"created_at":"2024-08-02T02:00:46.771Z","updated_at":"2025-06-30T20:04:48.213Z","avatar_url":"https://github.com/cloudposse-archives.png","language":"JavaScript","funding_links":["https://github.com/sponsors/cloudposse"],"categories":["Articles"],"sub_categories":[],"readme":"![Cloud Posse](https://cloudposse.com/logo-300x69.png)\n\n# load-testing\n\nA collection of best practices, workflows, scripts and scenarios that Cloud Posse uses for load and performance testing of websites and applications (in particular those deployed on Kubernetes clusters).\n\n__NOTE:__ All load testing scenarios in [scenarios](scenarios) are just examples and are provided here for reference.\nConsider updating them to reflect your environment.\n\n\n## Introduction\n\nFor load and performance testing, the workflow consists of these main steps:\n\n1. [Select and configure load testing tools](#select-and-configure-load-testing-tools)\n2. [Implement load testing scenarios and scripts](#implement-load-testing-scenarios-and-scripts)\n3. [Perform load testing and analyze the results](#perform-load-testing-and-analyze-the-results)\n4. [Suggest improvements and tuning procedures for the infrastructure and application under test](#suggest-improvements-and-tuning-procedures-for-the-infrastructure-and-application-under-test)\n\n\n## Select and configure load testing tools\n\nWe use [k6](https://github.com/loadimpact/k6) from [Load Impact](https://loadimpact.com/) for the following reasons:\n\n* **Open Source** - well documented (see [docs](https://docs.k6.io/docs)) and with simple command line usage\n* **Synthetic Testing** - allows to easily create load test scenarios based on virtual users and simulated traffic configurations\n* **Small Footprint** - implemented in [Go](https://golang.org/), which has excellent support for concurrency and small memory footprint\n* **JavaScript DSL** - scenario scripting in `JavaScript` ES2015/ES6 with support for local and remote modules\n* **Testing as Code** - test logic and configuration options are both in JS for version control friendliness\n* **Command-line Driven** - can be run from the command line with command \u0026 control through CLI\n* **Compatible with [HAR](http://www.softwareishard.com/blog/har-12-spec/)** - has a built-in [HAR](http://www.softwareishard.com/blog/har-12-spec/) converter that will read HAR files and convert them to `k6` scripts (see [session recording](https://docs.k6.io/docs/session-recording-har-support))\n* **Automated Testing** - can be easily integrated into CI/CD pipelines\n* **Comprehensive Metrics** - provides a comprehensive set of built-in [metrics](https://docs.k6.io/docs/result-metrics)\n* **Beautiful Visualizations** - can stream metrics into [InfluxDB](https://www.influxdata.com/) for storage and visualization with [Grafana](https://grafana.com/) (see [influxdb-grafana](https://docs.k6.io/docs/influxdb-grafana))\n\nRead more about k6's features and metrics:\n\n* [Features](https://docs.k6.io/docs/welcome#section-features)\n* [Interpret test results](http://support.loadimpact.com/knowledgebase/articles/174121-how-do-i-interpret-test-results)\n\n\n\n### Installation\n\nThe [docker-compose](docker-compose.yml) file builds three Docker images:\n\n* [InfluxDB](https://www.influxdata.com/)\n* [Grafana](https://grafana.com/)\n* [k6](https://github.com/loadimpact/k6)\n\nRun [docker-compose up](https://docs.docker.com/compose/reference/up/) to build the containers and run `InfluxDB` and `Grafana` in the background\n\n```sh\ndocker-compose up -d influxdb grafana\n```\n\nOpen http://localhost:3000 to see `Grafana` running.\n\nBy default, `Grafana` does not come with any pre-configured dashboards.\n\nWe will install this dashboard to visualize `k6` metrics https://grafana.com/dashboards/2587\n\nGo to `+/Import` menu and paste `https://grafana.com/dashboards/2587` URL into the `Grafana.com Dashboard` field, then click `Load` button.\nThen select `myinfluxdb` from the `Select a InfluxDB data source` dropdown and click `Import`.\n\n###\n\n![Import Grafana Dashboard](images/load-testing-grafana-setup-01.png)\n\n###\n\n\n## Implement load testing scenarios and scripts\n\nTo establish a baseline, first we'll load test the website's home page with one concurrent user.\n\nThis will allow us to see the best performing numbers, against which we'd compare more advanced scenarios involving more pages and more concurrent users.\n\n(see [scenario_01](scenarios/scenario_01.js))\n\n```js\nimport http from \"k6/http\";\nimport {check} from \"k6\";\nimport {config} from \"./utils.js\";\n\nexport function setup() {\n}\n\nexport function teardown(data) {\n}\n\nexport default function (data) {\n    let res = http.get(config.baseUrl);\n    check(res, {\"status is 200\": (r) =\u003e r.status === 200});\n}\n```\n\nRun the test\n\n```sh\ndocker-compose run -v $PWD/scenarios:/scenarios k6 run --vus 1 /scenarios/scenario_01.js\n```\n\n```sh\nexecution: local\n     output: influxdb=http://influxdb:8086/k6 (http://influxdb:8086)\n     script: /scenarios/scenario_01.js\n\n    duration: -,  iterations: 1\n         vus: 1, max: 1\n\n    done [==========================================================] 1 / 1\n\n    ✓ status is 200\n\n    checks.....................: 100.00% ✓ 1   ✗ 0\n    data_received..............: 21 kB   29 kB/s\n    data_sent..................: 628 B   864 B/s\n    http_req_blocked...........: avg=507.78ms min=507.78ms med=507.78ms max=507.78ms p(90)=507.78ms p(95)=507.78ms\n    http_req_connecting........: avg=101.94ms min=101.94ms med=101.94ms max=101.94ms p(90)=101.94ms p(95)=101.94ms\n    http_req_duration..........: avg=218.25ms min=218.25ms med=218.25ms max=218.25ms p(90)=218.25ms p(95)=218.25ms\n    http_req_receiving.........: avg=98.58ms  min=98.58ms  med=98.58ms  max=98.58ms  p(90)=98.58ms  p(95)=98.58ms\n    http_req_sending...........: avg=311.79µs min=311.79µs med=311.79µs max=311.79µs p(90)=311.79µs p(95)=311.79µs\n    http_req_tls_handshaking...: avg=233.84ms min=233.84ms med=233.84ms max=233.84ms p(90)=233.84ms p(95)=233.84ms\n    http_req_waiting...........: avg=119.36ms min=119.36ms med=119.36ms max=119.36ms p(90)=119.36ms p(95)=119.36ms\n    http_reqs..................: 1       1.377151/s\n    iteration_duration.........: avg=726.16ms min=726.16ms med=726.16ms max=726.16ms p(90)=726.16ms p(95)=726.16ms\n    iterations.................: 1       1.377151/s\n    vus........................: 1       min=1 max=1\n    vus_max....................: 1       min=1 max=1\n\n```\n\nOpen the `Grafana` dashboard at http://localhost:3000 to see the load test results\n\n###\n\n![Load Scenario 01 Grafana Dashboard](images/load-testing-grafana-scenario-01.png)\n\n###\n\n\nWe assume that we want the website to handle 50 concurrent users.\n\nLet's hit the home page with 50 concurrent users, each doing one iteration\n\n```sh\ndocker-compose run -v $PWD/scenarios:/scenarios k6 run --vus 50 -i 50 /scenarios/scenario_01.js\n```\n\n```sh\nexecution: local\n     output: influxdb=http://influxdb:8086/k6 (http://influxdb:8086)\n     script: /scenarios/scenario_01.js\n\n    duration: -,   iterations: 50\n         vus: 50, max: 50\n\n    done [==========================================================] 50 / 50\n\n    ✓ status is 200\n\n    checks.....................: 100.00% ✓ 50   ✗ 0\n    data_received..............: 1.1 MB  900 kB/s\n    data_sent..................: 32 kB   26 kB/s\n    http_req_blocked...........: avg=508.53ms min=367.91ms med=514.28ms max=626.1ms  p(90)=535.23ms p(95)=580.65ms\n    http_req_connecting........: avg=118.73ms min=107.93ms med=116.3ms  max=128.63ms p(90)=127.72ms p(95)=128.27ms\n    http_req_duration..........: avg=352.61ms min=242.46ms med=289.54ms max=693.7ms  p(90)=586.94ms p(95)=677.55ms\n    http_req_receiving.........: avg=142.61ms min=106.13ms med=112.35ms max=325.64ms p(90)=221.21ms p(95)=243.53ms\n    http_req_sending...........: avg=302.04µs min=96µs     med=216.3µs  max=1.47ms   p(90)=450.41µs p(95)=722.01µs\n    http_req_tls_handshaking...: avg=384.43ms min=255.68ms med=392.95ms max=490.64ms p(90)=400.86ms p(95)=445.49ms\n    http_req_waiting...........: avg=209.7ms  min=121.49ms med=178.65ms max=465.43ms p(90)=372.73ms p(95)=449.88ms\n    http_reqs..................: 50      41.106944/s\n    iteration_duration.........: avg=861.49ms min=613.3ms  med=821.16ms max=1.21s    p(90)=1.1s     p(95)=1.19s\n    iterations.................: 50      41.106944/s\n    vus........................: 50      min=50 max=50\n    vus_max....................: 50      min=50 max=50\n\n```\n\nWe just loaded the website with `41.106944` requests per second.\n\nLet's increase the number of iterations to hit the home page with approximately 50 requests per second.\n\n```sh\ndocker-compose run -v $PWD/scenarios:/scenarios k6 run --vus 50 -i 80 /scenarios/scenario_01.js\n```\n\n```sh\nexecution: local\n     output: influxdb=http://influxdb:8086/k6 (http://influxdb:8086)\n     script: /scenarios/scenario_01.js\n\n    duration: -,   iterations: 80\n         vus: 50, max: 50\n\n    done [==========================================================] 80 / 80\n\n    ✓ status is 200\n\n    checks.....................: 100.00% ✓ 80   ✗ 0\n    data_received..............: 1.6 MB  1.0 MB/s\n    data_sent..................: 36 kB   23 kB/s\n    http_req_blocked...........: avg=417.72ms min=0s       med=654.48ms max=773.72ms p(90)=752.66ms p(95)=755.02ms\n    http_req_connecting........: avg=72.56ms  min=0s       med=109.63ms max=126.36ms p(90)=124.42ms p(95)=125.01ms\n    http_req_duration..........: avg=365.54ms min=124.6ms  med=300.31ms max=798.99ms p(90)=675.51ms p(95)=767.64ms\n    http_req_receiving.........: avg=189.48ms min=383.2µs  med=116.58ms max=572.32ms p(90)=357.2ms  p(95)=553.45ms\n    http_req_sending...........: avg=171.3µs  min=56.4µs   med=156.7µs  max=557.4µs  p(90)=303.64µs p(95)=366.13µs\n    http_req_tls_handshaking...: avg=220.24ms min=0s       med=344.77ms max=446.4ms  p(90)=427.9ms  p(95)=429.37ms\n    http_req_waiting...........: avg=175.89ms min=121.14ms med=148.49ms max=478.35ms p(90)=238.48ms p(95)=265.03ms\n    http_reqs..................: 80      50.821139/s\n    iteration_duration.........: avg=783.68ms min=124.91ms med=972.43ms max=1.55s    p(90)=1.23s    p(95)=1.36s\n    iterations.................: 80      50.821139/s\n    vus........................: 50      min=50 max=50\n    vus_max....................: 50      min=50 max=50\n\n```\n\n\nCheck the Kubernetes pods CPU and memory consumption in the Kubernetes `Grafana` dashboard\n\n###\n\n![Load Scenario 01 Grafana Portal Dashboard](images/load-testing-portal-grafana-scenario-01.png)\n\n###\n\n\nWe can conclude that with the current CPU and memory configurations for Kubernetes pods, the site can handle 50 requests per second to the home page.\n\n\n## Perform load testing and analyze the results\n\nk6 has a built-in HAR converter that will read HAR files and convert them to k6 scripts that can then be executed.\n\nSee [session recording](https://docs.k6.io/docs/session-recording-har-support) for more details.\n\nWe recorded and prepared a sample scenario to test the complete user flow on a website, including signing up, creating a user profile, providing all required information, and finally getting a list of available options for the user (see [scenario_all](scenarios/scenario_all.js)).\n\nRun it with a single user\n\n```sh\ndocker-compose run -v $PWD/scenarios:/scenarios k6 run --vus 1 -i 1 /scenarios/scenario_all.js\n```\n\n```sh\nexecution: local\n     output: influxdb=http://influxdb:8086/k6 (http://influxdb:8086)\n     script: /scenarios/scenario_all.js\n\n    duration: -,  iterations: 1\n         vus: 1, max: 1\n\n    done [==========================================================] 1 / 1\n\n    █ page_01 - home\n\n    █ page_02 - /profile\n\n    █ page_03 - /save_profile\n\n    █ page_04 - /add_categories\n\n    █ page_05 - /add_features\n\n    █ page_06 - /add_details\n\n    █ page_07 - /add_details2\n\n    █ page_08 - /users\n\n    █ page_09 - /enrollment\n\n    █ page_10 - /enrollment2\n\n    █ page_11 - /update_profile\n\n    data_received..............: 14 MB  630 kB/s\n    data_sent..................: 234 kB 11 kB/s\n    group_duration.............: avg=1.96s    min=106.14ms med=1.75s    max=4.91s    p(90)=3.76s    p(95)=4.34s\n    http_req_blocked...........: avg=33.98ms  min=0s       med=0s       max=443.45ms p(90)=0s       p(95)=441.04ms\n    http_req_connecting........: avg=7.36ms   min=0s       med=0s       max=96.85ms  p(90)=0s       p(95)=95.41ms\n    http_req_duration..........: avg=227.61ms min=95.64ms  med=148.8ms  max=1.27s    p(90)=464.57ms p(95)=806.93ms\n    http_req_receiving.........: avg=34.44ms  min=76.3µs   med=1.12ms   max=1.11s    p(90)=102.9ms  p(95)=117.98ms\n    http_req_sending...........: avg=224.35µs min=83.5µs   med=178.1µs  max=1.45ms   p(90)=346.46µs p(95)=545.93µs\n    http_req_tls_handshaking...: avg=17.26ms  min=0s       med=0s       max=225.33ms p(90)=0s       p(95)=224.26ms\n    http_req_waiting...........: avg=192.94ms min=95.41ms  med=105.15ms max=998.45ms p(90)=374.83ms p(95)=652.32ms\n    http_reqs..................: 130    6.027408/s\n    iteration_duration.........: avg=21.56s   min=21.56s   med=21.56s   max=21.56s   p(90)=21.56s   p(95)=21.56s\n    iterations.................: 1      0.046365/s\n    vus........................: 1      min=1 max=1\n    vus_max....................: 1      min=1 max=1\n\n```\n\nThe entire process took 21 seconds.\n\nNow run it with 50 concurrent users\n\n```sh\ndocker-compose run -v $PWD/scenarios:/scenarios k6 run --vus 50 -i 50 /scenarios/scenario_all.js\n```\n\n```sh\nexecution: local\n     output: influxdb=http://influxdb:8086/k6 (http://influxdb:8086)\n     script: /scenarios/scenario_all.js\n\n    duration: -,   iterations: 50\n         vus: 50, max: 50\n\n    done [==========================================================] 50 / 50\n\n    █ page_01 - home\n\n    █ page_02 - /profile\n\n    █ page_03 - /save_profile\n\n    █ page_04 - /add_categories\n\n    █ page_05 - /add_features\n\n    █ page_06 - /add_details\n\n    █ page_07 - /add_details2\n\n    █ page_08 - /users\n\n    █ page_09 - /enrollment\n\n    █ page_10 - /enrollment2\n\n    █ page_11 - /update_profile\n\n    data_received..............: 679 MB 6.6 MB/s\n    data_sent..................: 12 MB  115 kB/s\n    group_duration.............: avg=5.78s    min=104.4ms    med=3.02s    max=1m6s     p(90)=10.88s   p(95)=13.51s\n    http_req_blocked...........: avg=230.04ms min=0s         med=0s       max=5.64s    p(90)=0s       p(95)=2.93s\n    http_req_connecting........: avg=10.63ms  min=0s         med=0s       max=321.33ms p(90)=0s       p(95)=123.46ms\n    http_req_duration..........: avg=953.25ms min=128.3µs    med=292.67ms max=59.93s   p(90)=2.22s    p(95)=3.19s\n    http_req_receiving.........: avg=223.82ms min=-15.0602ms med=2.04ms   max=59.78s   p(90)=389.02ms p(95)=1.14s\n    http_req_sending...........: avg=221.58µs min=70.8µs     med=155.4µs  max=8.2ms    p(90)=337µs    p(95)=469.13µs\n    http_req_tls_handshaking...: avg=206.19ms min=0s         med=0s       max=5.24s    p(90)=0s       p(95)=2.59s\n    http_req_waiting...........: avg=729.2ms  min=0s         med=199.58ms max=59.7s    p(90)=1.96s    p(95)=2.86s\n    http_reqs..................: 6500   63.046647/s\n    iteration_duration.........: avg=1m3s     min=31.83s     med=50.92s   max=1m43s    p(90)=1m39s    p(95)=1m40s\n    iterations.................: 50     0.484974/s\n    vus........................: 50     min=50 max=50\n    vus_max....................: 50     min=50 max=50\n\n```\n\nCheck the Kubernetes pods CPU and memory consumption in the Kubernetes `Grafana` dashboard\n\n###\n\n![Load Scenario 02 Grafana Portal Dashboard](images/load-testing-portal-grafana-scenario-02.png)\n\n###\n\nFrom the load test stats and graphs above, we can conclude that the provisioned CPU and memory resources on the Kubernetes cluster are enough to sustain 50 concurrent users going through the entire flow.\n\n\n## Suggest improvements and tuning procedures for the infrastructure and application under test\n\nHere are some optimization steps that we usually perform after running load tests:\n\n* Put all static assets behind a CDN (e.g. AWS CloudFront), do not overload the Kubernetes pods with serving the static assets\n* [Scale Cluster Horizontally](https://docs.cloudposse.com/kubernetes-optimization/scale-cluster-horizontally) - Scale Kubernetes cluster horizontally by adding nodes\n* [Scale Cluster Vertically](https://docs.cloudposse.com/kubernetes-optimization/scale-cluster-vertically) - Scale Kubernetes cluster vertically by using different types of EC2 instances\n* [Scale Pods Horizontally](https://docs.cloudposse.com/kubernetes-optimization/scale-pods-horizontally) - Scale Kubernetes pods horizontally by increasing the replica count\n* [Scale Pods Vertically](https://docs.cloudposse.com/kubernetes-optimization/scale-pods-vertically) - Scale Kubernetes pods vertically by increasing CPU and Memory limits\n* [Scale Nginx Ingress Horizontally](https://docs.cloudposse.com/kubernetes-optimization/scale-nginx-ingress-horizontally) - Scale Nginx Ingress pods horizontally by increasing the replica count\n* [Scale Nginx Ingress Vertically](https://docs.cloudposse.com/kubernetes-optimization/scale-nginx-ingress-vertically) - Scale Nginx Ingress vertically by increasing CPU and Memory limits\n* [Tune Nginx](https://docs.cloudposse.com/kubernetes-optimization/tune-nginx) - Tune Nginx parameters (timeouts, worker processes, logs, http)\n* Optimize application and web servers' parameters (e.g. concurrency, threads and processes, thread pools, timeouts, memory limits)\n* [Optimize databases](https://docs.cloudposse.com/kubernetes-optimization/optimize-database-indexes) - Optimize database queries and indexes\n\n\nFor more details, have a look at our comprehensive [load testing documentation](https://docs.cloudposse.com/load-testing/) on our [Cloud Posse Developer Hub](https://docs.cloudposse.com).\n\n\n## Credits\n\nThanks to [Load Impact](https://loadimpact.com/) for the excellent [k6](https://github.com/loadimpact/k6) tool and [examples of load testing scenarios](https://github.com/loadimpact/k6/tree/master/samples)\n\n\n## Help\n\n**Got a question?**\n\nFile a GitHub [issue](https://github.com/cloudposse/load-testing/issues), send us an [email](mailto:hello@cloudposse.com) or reach out to us on [Gitter](https://gitter.im/cloudposse/).\n\n\n## Contributing\n\n### Bug Reports \u0026 Feature Requests\n\nPlease use the [issue tracker](https://github.com/cloudposse/load-testing/issues) to report any bugs or file feature requests.\n\n### Developing\n\nIf you are interested in being a contributor and want to get involved in developing `load-testing`, we would love to hear from you! Shoot us an [email](mailto:hello@cloudposse.com).\n\nIn general, PRs are welcome. We follow the typical \"fork-and-pull\" Git workflow.\n\n 1. **Fork** the repo on GitHub\n 2. **Clone** the project to your own machine\n 3. **Commit** changes to your own branch\n 4. **Push** your work back up to your fork\n 5. Submit a **Pull request** so that we can review your changes\n\n**NOTE:** Be sure to merge the latest from \"upstream\" before making a pull request!\n\n\n## License\n\n[APACHE 2.0](LICENSE) © 2018 [Cloud Posse, LLC](https://cloudposse.com)\n\nSee [LICENSE](LICENSE) for full details.\n\n    Licensed to the Apache Software Foundation (ASF) under one\n    or more contributor license agreements.  See the NOTICE file\n    distributed with this work for additional information\n    regarding copyright ownership.  The ASF licenses this file\n    to you under the Apache License, Version 2.0 (the\n    \"License\"); you may not use this file except in compliance\n    with the License.  You may obtain a copy of the License at\n\n      http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing,\n    software distributed under the License is distributed on an\n    \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n    KIND, either express or implied.  See the License for the\n    specific language governing permissions and limitations\n    under the License.\n\n\n## About\n\n`load-testing` is maintained and funded by [Cloud Posse, LLC][website].\n\n![Cloud Posse](https://cloudposse.com/logo-300x69.png)\n\n\nLike it? Please let us know at \u003chello@cloudposse.com\u003e\n\nWe love [Open Source Software](https://github.com/cloudposse/)!\n\nSee [our other projects][community]\nor [hire us][hire] to help build your next cloud platform.\n\n  [website]: https://cloudposse.com/\n  [community]: https://github.com/cloudposse/\n  [hire]: https://cloudposse.com/contact/\n\n\n## Contributors\n\n| [![Erik Osterman][erik_img]][erik_web]\u003cbr/\u003e[Erik Osterman][erik_web] | [![Andriy Knysh][andriy_img]][andriy_web]\u003cbr/\u003e[Andriy Knysh][andriy_web] |[![Igor Rodionov][igor_img]][igor_web]\u003cbr/\u003e[Igor Rodionov][igor_img]|[![Sarkis Varozian][sarkis_img]][sarkis_web]\u003cbr/\u003e[Sarkis Varozian][sarkis_web] |\n|-------------------------------------------------------|------------------------------------------------------------------|------------------------------------------------------------------|------------------------------------------------------------------|\n\n[erik_img]: http://s.gravatar.com/avatar/88c480d4f73b813904e00a5695a454cb?s=144\n[erik_web]: https://github.com/osterman/\n[andriy_img]: https://avatars0.githubusercontent.com/u/7356997?v=4\u0026u=ed9ce1c9151d552d985bdf5546772e14ef7ab617\u0026s=144\n[andriy_web]: https://github.com/aknysh/\n[igor_img]: http://s.gravatar.com/avatar/bc70834d32ed4517568a1feb0b9be7e2?s=144\n[igor_web]: https://github.com/goruha/\n[sarkis_img]: https://avatars3.githubusercontent.com/u/42673?s=144\u0026v=4\n[sarkis_web]: https://github.com/sarkis/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudposse-archives%2Fload-testing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudposse-archives%2Fload-testing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudposse-archives%2Fload-testing/lists"}