diff --git a/README.md b/README.md
index 722b796..f16e447 100644
--- a/README.md
+++ b/README.md
@@ -49,3 +49,56 @@ POST|/v1/produce|Add produce items to the catalogue.|`[{"code":"string","name":"
GET|/v1/produce/{produceCode}|Get the produce item with the given produceCode.|`null`|200 OK
400 Bad Request
500 Internal Server Error
DELETE|/v1/produce/{produceCode}|Delete the produce item with the given produceCode.|`null`|204 No Content
400 Bad Request
500 Internal Server Error
+## Load Test
+
+This application was load tested using K6. To run the load test follow the installation documentation for K6 [here](https://k6.io/docs/getting-started/installation/). Once installed, make sure Supermarket-API is running and initiate the load test by running:
+
+```
+$~ k6 run loadtests/load-test.js
+```
+
+The load test is configured to ramp up to 50 iterations per second over a 4 minute period and then maintain that load for a period of 1 minute. Each iteration adds a new unique produce item, and then queries all items catalogued in the service.
+
+Load test results below:
+```
+
+ /\ |‾‾| /‾‾/ /‾‾/
+ /\ / \ | |/ / / /
+ / \/ \ | ( / ‾‾\
+ / \ | |\ \ | (‾) |
+ / __________ \ |__| \__\ \_____/ .io
+
+ execution: local
+ script: loadtests/load-test.js
+ output: -
+
+ scenarios: (100.00%) 2 scenarios, 500 max VUs, 5m30s max duration (incl. graceful stop):
+ * ramp_to_load: Up to 50.00 iterations/s for 4m0s over 1 stages (maxVUs: 200-250, gracefulStop: 30s)
+ * maintain_load: 50.00 iterations/s for 1m0s (maxVUs: 200-250, startTime: 4m0s, gracefulStop: 30s)
+
+
+running (5m00.1s), 000/400 VUs, 9000 complete and 0 interrupted iterations
+ramp_to_load ✓ [======================================] 200/200 VUs 4m0s 50 iters/s
+maintain_load ✓ [======================================] 200/200 VUs 1m0s 50 iters/s
+
+ ✓ AddProduceOK...................: 100.00% ✓ 9000 ✗ 0
+ ✓ AddProduceTiming...............: avg=0.706569 min=0.195315 med=0.465269 max=15.900239 p(90)=1.499495 p(95)=1.846937
+ ✓ GetProduceOK...................: 100.00% ✓ 9000 ✗ 0
+ ✓ GetProduceTiming...............: avg=30.18456 min=0.302081 med=27.981297 max=99.590601 p(90)=57.708492 p(95)=63.63907
+ data_received..................: 3.3 GB 11 MB/s
+ data_sent......................: 2.6 MB 8.5 kB/s
+ http_req_blocked...............: avg=16.31µs min=1.15µs med=4.26µs max=7.21ms p(90)=15.23µs p(95)=21.52µs
+ http_req_connecting............: avg=8.18µs min=0s med=0s max=7.13ms p(90)=0s p(95)=0s
+ http_req_duration..............: avg=15.44ms min=195.31µs med=2.28ms max=99.59ms p(90)=49.71ms p(95)=57.7ms
+ { expected_response:true }...: avg=15.44ms min=195.31µs med=2.28ms max=99.59ms p(90)=49.71ms p(95)=57.7ms
+ http_req_failed................: 0.00% ✓ 0 ✗ 18000
+ http_req_receiving.............: avg=260.07µs min=16.67µs med=129.53µs max=8.89ms p(90)=594.14µs p(95)=883.46µs
+ http_req_sending...............: avg=34.61µs min=5.6µs med=24.85µs max=583.87µs p(90)=81.81µs p(95)=115.66µs
+ http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s
+ http_req_waiting...............: avg=15.15ms min=160.47µs med=2.04ms max=98.86ms p(90)=48.99ms p(95)=56.93ms
+ http_reqs......................: 18000 59.988732/s
+ iteration_duration.............: avg=31.42ms min=1.51ms med=29.3ms max=102.12ms p(90)=59.07ms p(95)=65.16ms
+ iterations.....................: 9000 29.994366/s
+ vus............................: 200 min=200 max=200
+ vus_max........................: 400 min=400 max=400
+```
diff --git a/loadtests/load-test.js b/loadtests/load-test.js
new file mode 100644
index 0000000..bdf1a9b
--- /dev/null
+++ b/loadtests/load-test.js
@@ -0,0 +1,60 @@
+import http from 'k6/http';
+import { sleep } from 'k6';
+import { Rate, Trend } from 'k6/metrics';
+
+const getProduceSuccessRate = new Rate('GetProduceOK');
+const getProduceTimingTrend = new Trend('GetProduceTiming');
+
+const addProduceSuccessRate = new Rate('AddProduceOK');
+const addProduceTimingTrend = new Trend('AddProduceTiming');
+
+export const options = {
+ scenarios: {
+ ramp_to_load: {
+ executor: 'ramping-arrival-rate',
+ startRate: 0,
+ preAllocatedVUs: 200,
+ maxVUs: 250,
+ stages: [
+ { duration: '4m', target: 50, },
+ ],
+ },
+ maintain_load: {
+ executor: 'constant-arrival-rate',
+ rate: 50,
+ timeUnit: '1s',
+ startTime: '4m',
+ duration: '1m',
+ preAllocatedVUs: 200,
+ maxVUs: 250,
+ },
+ },
+ thresholds: {
+ GetProduceOK: ['rate==1'],
+ GetProduceTiming: ['p(90)<100','p(95)<200'],
+
+ AddProduceOK: ['rate==1'],
+ AddProduceTiming: ['p(90)<100','p(95)<200'],
+ },
+}
+
+export default function() {
+ const id = `${__ITER}-${__VU}`
+
+ const addRes = http.post('http://localhost:3000/v1/produce', JSON.stringify([{
+ code: `code-${id}`,
+ name: `name-${id}`,
+ price: {
+ amount: 100,
+ currency: "USD"
+ }
+ }]))
+
+ const getRes = http.get('http://localhost:3000/v1/produce')
+
+ addProduceSuccessRate.add(addRes.status < 300)
+ addProduceTimingTrend.add(addRes.timings.duration)
+
+ getProduceSuccessRate.add(getRes.status < 300)
+ getProduceTimingTrend.add(getRes.timings.duration)
+}