TT Lab
Get started
Learn Learning paths Courses

Load Testing

Where does the test's target number come from?

Continue in TT Lab

Goal

From four weeks of hourly traffic data, you apply, in order, the daily total, the peak hour, the safety factor, the failure margin, and the growth rate to derive the target RPS for a load test, and then actually apply that target to confirm whether it can be produced in this environment.

Why it matters

The field most often left blank in a load test plan is the source of the target RPS. If you ask where '1,000 requests per second' came from, there is usually no answer, and then even if the test passes, you cannot say what was guaranteed. The target must be derived from operational data. The average, the daily total divided by 86400, is almost always several times smaller than the real peak, and if you size capacity on that average, you are short by exactly that multiple. On top of that, headroom so as not to use all the capacity even at peak, margin to survive losing one zone, and the growth rate until the next planning cycle are multiplied in turn. Finally, you must confirm once whether the target fixed that way can actually be applied — a pass obtained with a load you could not apply is not a pass.

Steps

  1. /opt/lab/lt/lt-capacity-target/traffic.tsv is four weeks of hourly request counts (after one header line, 날짜 시각 요청수, that is, date, hour, and request count, separated by tabs). Write the per-date totals to /root/lt-capacity-target/daily.tsv as 28 lines of two tab-separated columns, <날짜> <하루 총 요청 수> (date and total requests for the day), and write two lines, peak_date= and peak_total=, to /root/lt-capacity-target/01-peak-day.txt. This is the busiest day.
  2. Find the busiest single hour within the 24 hours of the busiest day and write three lines to /root/lt-capacity-target/02-peak-hour.txt: peak_hour= (an integer 0..23), peak_hour_requests= (the number of requests in that one hour), and peak_share= (the share that one hour takes of that day's total, to four decimal places).
  3. Write three lines to /root/lt-capacity-target/03-rps.txt. avg_rps= is the busiest day's total divided by 86400, peak_rps= is the number of requests in the busiest hour divided by 3600 (both to two decimal places), and peak_over_avg= is the ratio of the two (to two decimal places).
  4. Set the operating margin (headroom) at 30% — meaning you will use only 70% of capacity even at peak. Write two lines to /root/lt-capacity-target/04-headroom.txt, headroom=0.30 and rps_after_headroom=. For the second value, write peak_rps ÷ (1 − headroom) to two decimal places.
  5. The service is placed evenly across 4 zones and must handle the peak even if one zone is lost entirely. Write three lines to /root/lt-capacity-target/05-nplus1.txt, nodes=4, surviving=3, and rps_after_nplus1=. For the last value, write rps_after_headroom × nodes ÷ surviving to two decimal places.
  6. Traffic is growing 8% per month and this capacity must last 6 months. Write four lines to /root/lt-capacity-target/06-growth.txt: monthly_growth=0.08, months=6, growth_factor= (1.08 to the 6th power, to four decimal places), and rps_after_growth= (rps_after_nplus1 × growth_factor, to two decimal places).
  7. Create /root/lt-capacity-target/target.tsv. It has five lines with no header, and each line has two tab-separated columns, <단계> <RPS> (stage and RPS). The stage names are, in order, peak, headroom, nplus1, growth, and target; the first four lines take the values you wrote in the previous steps, and the last target line takes rps_after_growth rounded up to an integer. Then write two lines to /root/lt-capacity-target/07-note.txt, test_target_rps= (that integer) and reason= (where this target came from, at least 60 characters).
  8. Start /opt/lab/lt/lt-capacity-target/echo.py on port 8095 and actually apply the target you set in step 7. Use 20 workers, a per-worker rate limit of 올림(목표 ÷ 20) (that is, the target divided by 20, rounded up), and a request count of 목표 × 5 (that is, the target times 5), and leave the raw CSV in /root/lt-capacity-target/run.csv. Then write five lines to /root/lt-capacity-target/08-run.txt: target_rps=, workers=20, q_per_worker=, measured_rps= (the value recomputed from run.csv, to two decimal places), and reached= (yes if measured is 90% or more of the target, otherwise no), and a note= of at least 50 characters.

Notes

First count the daily total

/opt/lab/lt/lt-capacity-target/traffic.tsv is four weeks of hourly request counts (after one header line, 날짜 시각 요청수, that is, date, hour, and request count, separated by tabs). Write the per-date totals to /root/lt-capacity-target/daily.tsv as 28 lines of two tab-separated columns, <날짜> <하루 총 요청 수> (date and total requests for the day), and write two lines, peak_date= and peak_total=, to /root/lt-capacity-target/01-peak-day.txt. This is the busiest day.

You can just add up the third column by date with awk -F'\t'. Skip the one header line. The basis of capacity planning is not the average but the busiest day — if you set it by the average, it collapses on that day.

When was the busiest time within that day

Find the busiest single hour within the 24 hours of the busiest day and write three lines to /root/lt-capacity-target/02-peak-hour.txt: peak_hour= (an integer 0..23), peak_hour_requests= (the number of requests in that one hour), and peak_share= (the share that one hour takes of that day's total, to four decimal places).

If the 24 hours were even, one hour's share would be 1 ÷ 24 = 0.0417. The point of this step is how many times larger the actual value is than that — that multiple is exactly 'how short you would be if you planned by the average'.

How many times short is the value divided by the average

Write three lines to /root/lt-capacity-target/03-rps.txt. avg_rps= is the busiest day's total divided by 86400, peak_rps= is the number of requests in the busiest hour divided by 3600 (both to two decimal places), and peak_over_avg= is the ratio of the two (to two decimal places).

The daily total ÷ 86400 is the value 'if that day had been equally busy for all 24 hours'. The real peak is far larger than that. If you do not know this multiple and size capacity on the average, you are short by exactly this multiple at peak time.

Leave margin and raise the target

Set the operating margin (headroom) at 30% — meaning you will use only 70% of capacity even at peak. Write two lines to /root/lt-capacity-target/04-headroom.txt, headroom=0.30 and rps_after_headroom=. For the second value, write peak_rps ÷ (1 − headroom) to two decimal places.

If you use 100% of capacity at peak, you are already sitting at the point where queues start to build. In queueing theory, as utilization approaches 1, wait time increases sharply. So you set the target above the peak. It is division — not multiplying by 0.7.

Make it withstand losing one zone

The service is placed evenly across 4 zones and must handle the peak even if one zone is lost entirely. Write three lines to /root/lt-capacity-target/05-nplus1.txt, nodes=4, surviving=3, and rps_after_nplus1=. For the last value, write rps_after_headroom × nodes ÷ surviving to two decimal places.

To take the same load with only 3 of the 4 zones left, the whole must have 4/3 times the capacity. So the load you have to confirm in the test goes up by that much. If you leave out this factor, it is fine in normal times and collapses only on the day one zone is lost — the worst way to fail.

Is it a target that is still usable half a year later

Traffic is growing 8% per month and this capacity must last 6 months. Write four lines to /root/lt-capacity-target/06-growth.txt: monthly_growth=0.08, months=6, growth_factor= (1.08 to the 6th power, to four decimal places), and rps_after_growth= (rps_after_nplus1 × growth_factor, to two decimal places).

It is compound — not 8% × 6 = 48% but 1.08 to the 6th power. Calculate yourself by what percent the difference between the two changes the target figure. In principle the growth rate should be estimated from the data, but in this step you take it as the value received from product planning and focus on the calculation method.

Leave where the target came from in one file

Create /root/lt-capacity-target/target.tsv. It has five lines with no header, and each line has two tab-separated columns, <단계> <RPS> (stage and RPS). The stage names are, in order, peak, headroom, nplus1, growth, and target; the first four lines take the values you wrote in the previous steps, and the last target line takes rps_after_growth rounded up to an integer. Then write two lines to /root/lt-capacity-target/07-note.txt, test_target_rps= (that integer) and reason= (where this target came from, at least 60 characters).

This one table is the answer to the question 'where did 1,000 requests per second come from?' Looking at the four lines, you can also see at a glance how much the target moves if you change an assumption — mentally calculate what the target becomes if you lower the headroom to 20%.

Can that target actually be applied in this environment

Start /opt/lab/lt/lt-capacity-target/echo.py on port 8095 and actually apply the target you set in step 7. Use 20 workers, a per-worker rate limit of 올림(목표 ÷ 20) (that is, the target divided by 20, rounded up), and a request count of 목표 × 5 (that is, the target times 5), and leave the raw CSV in /root/lt-capacity-target/run.csv. Then write five lines to /root/lt-capacity-target/08-run.txt: target_rps=, workers=20, q_per_worker=, measured_rps= (the value recomputed from run.csv, to two decimal places), and reached= (yes if measured is 90% or more of the target, otherwise no), and a note= of at least 50 characters.

The total RPS is 요청 수 ÷ (max(offset + response-time) − min(offset)) (that is, the number of requests divided by the span from the earliest offset to the latest offset plus response time). If you could not apply the target, that is not a conclusion about the server but the limit of the generator, and you must write that fact in the report — if you do not, the next person reads this number as the server's capability.