Load tests from access logs: replaying real traffic in a test environment
A hand-written load test guesses which endpoints users really hit and how often. Spitfire takes this mix and the curve over the day from an access log or a trace file, and generates a test that drives each endpoint at its observed rate. This page walks through preparing the file, reading it and pointing the generated test at a test environment.
Which files are read?
The file can be up to 512 MB. The format is detected, or you pick it by hand:
| Format | Note |
|---|---|
| nginx (combined) | nginx's default access.log format; Apache's combined format is the same |
| JSON log lines | One JSON record per line (method, path, status, latency, time fields) |
| AWS ALB access log | The log the Application Load Balancer writes to S3 |
| AWS Classic ELB access log | A .gz file works too |
| CSV | Header method,path,status,latency,timestamp; latency in milliseconds |
| OTLP JSON (trace) | An OpenTelemetry trace export; server spans become requests |
| Jaeger JSON (trace) | Traces downloaded from the Jaeger UI or API |
1. Prepare the file
Pick the log of a busy day; you narrow the window in Spitfire later. The commands write the log into your home folder as one file.
nginx (rotated and compressed files included)
zcat -f /var/log/nginx/access.log* > $HOME/nginx-access.logAWS ALB
aws s3 cp s3://BUCKET/AWSLogs/ACCOUNT/elasticloadbalancing/REGION/2026/11/06/ $HOME/alb-logs --recursivezcat $HOME/alb-logs/*.gz > $HOME/alb-access.logReplace BUCKET, ACCOUNT and REGION with the values in your load balancer's log settings, and the date with your own day.
2. Read the file
- Click Tests → From real traffic.
- Choose the Log or trace file; leave Format on Detect the format.
- Press Read. The summary says M requests out of N records; records that could not be read and secret values dropped while reading are counted separately.
Success check: if the request count is close to the record count, the format was read correctly. If it is zero or very low, pick the Format by hand and read again.
3. Pick the time window and the mix
- Time window: set From (your local time) and To, or press Busiest hour / Whole file.
- Look at the Endpoint mix table. Paths are normalized:
/orders/123→/orders/:id; UUIDs, hashes, dates, opaque tokens and path segments with 20 or more distinct values become parameters.
The busiest hour of a made-up shop log; the numbers only show how the table reads:
| Endpoint | Requests | Share | Avg/s |
|---|---|---|---|
GET /products/:id | 216.000 | %60 | 60 |
GET /search | 72.000 | %20 | 20 |
GET /cart | 43.200 | %12 | 12 |
POST /cart/items | 21.600 | %6 | 6 |
POST /orders | 7.200 | %2 | 2 |
4. Point the test at the test environment
- Base URL: the server in the log is suggested; type the address of your test environment here. In the test it becomes
{{base}}. - Scale factor: 0.01–100. 1 is the observed traffic, 2 twice that, 0.1 a tenth. Start low on a small test environment.
- Endpoints in the test: 20 by default, at most 50; the most frequent ones are taken and the rest are left out.
- Read the What the test will do summary (coverage, stage length, peak rate) and press Create the test. Endpoints that change data (POST, PUT, DELETE) need a separate confirmation, as in the API document import.
Each endpoint becomes a ramping-arrival-rate scenario whose stages follow its own observed rate; together the scenarios replay the mix and the curve. This is an open load model: requests keep arriving at the log's rate even when the system slows down (load test types and load models).
5. Add bodies, headers and credentials
Access logs have no request bodies or headers. Open the test in the editor; add the bodies to the POST and PUT steps and, if needed, a login step and the Authorization header. For path parameters (:id), give values that really exist in the test environment from a data file.
Success check: run a one-VU trial with Try; every step should return 2xx. A 404 usually means the base URL still points at production, or the path parameters have no match in the test environment.
Privacy
- The file is read line by line and is not stored.
- Only derived values (time, method, path template, status, latency) stay in the controller's memory, for an hour at most, and are deleted once the test is created.
- Client addresses, users, user agents and headers are never read.
- Secret-looking query values and path segments (tokens, passwords, session IDs, e-mail addresses) are dropped while reading.
Frequently asked questions
What do I need to replay production traffic in a load test?Tests
Is the log file stored in Spitfire?Security
Can I test with twice the traffic?Tests
Why does the generated test get 404s?Tests
How is this different from a browser recording or an API document?Tests
Spitfire installs on Docker or Kubernetes with one command; every testing feature and protocol is open in the free edition.