15 Ready-to-Use Performance Testing Templates for Web, API, and Infrastructure
This article provides a collection of fifteen ready‑to‑use performance‑testing templates covering web page load, API peak load, database slow‑query, cache‑break, file‑upload bandwidth, WebSocket connections, microservice latency, OAuth2 flow, message‑queue lag, memory‑leak detection, SSL/TLS handshake, container CPU limits, and chaos‑mesh failover, each with clear objectives, tools, and sample code.
Template 1: Web Page Baseline Performance Test
Goal: Measure first‑screen load time < 2 s and First Contentful Paint (FCP) < 1.5 s for the e‑commerce homepage.
you are a mid‑level performance test engineer, design a baseline test for the e‑commerce homepage:
- URL: https://shop.example.com
- Metrics: first‑screen load time < 2s, FCP < 1.5s
- Tool: Locust + Playwright
- Output:
1. Test scenario description (including user behavior)
2. Locust script that integrates Playwright to measure front‑end metrics from locust import HttpUser, task
from playwright.sync_api import sync_playwright
class HomePageUser(HttpUser):
@task
def load_homepage(self):
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://shop.example.com")
# Get front‑end performance metrics
fcp = page.evaluate("performance.getEntriesByName('first-contentful-paint')[0].startTime")
load_time = page.evaluate("performance.timing.loadEventEnd - performance.timing.navigationStart")
# Report to Locust
self.environment.events.request_success.fire(
request_type="PAGE", name="/", response_time=load_time, response_length=0)
browser.close()Template 2: API Peak Load Test
Goal: Verify that the user‑query API can sustain 1 000 requests per second (RPS) with an error rate below 0.1 % while the database connection pool is limited to 100 connections.
Design a peak‑load test for the user‑query API:
- Endpoint: GET /api/v1/users?limit=100
- Target: 1000 RPS, error rate < 0.1 %
- Constraint: DB connection pool size = 100
- Generate a Locust script that includes dynamic parameters and result assertions. from locust import HttpUser, task, between
class UserQueryUser(HttpUser):
wait_time = between(1, 3)
@task
def get_users(self):
with self.client.get("/api/v1/users?limit=100", catch_response=True) as resp:
if resp.status_code != 200:
resp.failure(f"HTTP {resp.status_code}")
elif len(resp.json()) != 100:
resp.failure("Insufficient number of results")Template 3: Database Slow‑Query Load Test
Goal: Validate pagination performance on the orders table (10 000 rows, deep pagination page = 1000) and ensure the query finishes within 2 seconds while checking the execution plan.
Validate order‑table pagination performance:
- SQL: SELECT * FROM orders WHERE user_id=? ORDER BY created_at DESC LIMIT ?
- Scenario: 100 000 rows, deep pagination (page=1000)
- Tool: pytest + SQLAlchemy simulation
- Output test code that includes EXPLAIN analysis. import pytest
from sqlalchemy import text
def test_deep_pagination_performance(db_session):
# Insert 100 000 orders for user 1
for i in range(100000):
db_session.execute(text("INSERT INTO orders (user_id) VALUES (1)"))
db_session.commit()
# Test deep pagination
start_time = time.time()
result = db_session.execute(text("SELECT * FROM orders WHERE user_id=1 ORDER BY created_at DESC LIMIT 10 OFFSET 99990"))
query_time = time.time() - start_time
assert query_time < 2.0 # Must be < 2 s
# Verify index usage
explain = db_session.execute(text("EXPLAIN SELECT * FROM orders WHERE user_id=1 ORDER BY created_at DESC LIMIT 10"))
assert "Using index" in str(explain.fetchone())Template 4: Cache‑Break Scenario Test
Goal: Simulate a cache‑break on a product‑detail API (Redis TTL = 60 s) with 1 000 concurrent requests and observe whether the database QPS spikes.
Simulate cache‑break impact on product‑detail endpoint:
- Endpoint: GET /api/v1/products/123
- Cache: Redis, TTL = 60 s
- Scenario: Cache expires instantly, 1000 concurrent requests
- Generate a Gatling script to verify database QPS increase. class CacheBreakTest extends Simulation {
val httpProtocol = http.baseUrl("https://api.example.com")
val scn = scenario("Cache Break")
.exec(http("Product Detail").get("/api/v1/products/123"))
setUp(scn.inject(atOnceUsers(1000))).protocols(httpProtocol)
}Template 5: File Upload Bandwidth Test
Goal: Upload a 1 GB random binary file to the upload endpoint and achieve at least 80 % of a 1 Gbps network bandwidth.
Test large‑file upload bandwidth utilization:
- Endpoint: POST /api/v1/upload
- File: 1 GB random binary
- Target: Use >80 % of 1 Gbps bandwidth
- Generate a Python script using requests‑toolbelt for chunked upload and calculate throughput. import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
import time, os
def test_upload_bandwidth():
# Generate 1 GB random file
with open("large_file.bin", "wb") as f:
f.write(os.urandom(1024*1024*1024))
start_time = time.time()
with open("large_file.bin", "rb") as f:
encoder = MultipartEncoder({"file": ("large_file.bin", f, "application/octet-stream")})
resp = requests.post("/api/v1/upload", data=encoder, headers={"Content-Type": encoder.content_type})
duration = time.time() - start_time
throughput = (1024 / duration) # MB/s
assert throughput > 100 # >100 MB/s (~80 % of 1 Gbps)Template 6: WebSocket Connection Count Test
Goal: Verify that a WebSocket service can handle 10 000 concurrent connections while keeping memory usage under 4 GB.
Validate WebSocket service maximum connections:
- Service: wss://chat.example.com
- Target: Support 10 000 concurrent connections
- Monitor: Memory usage < 4 GB
- Generate an Artillery script that maintains connections and exchanges messages. # artillery.yaml
config:
target: "wss://chat.example.com"
phases:
- duration: 600
arrivalRate: 100 # 100 connections per second, 10 min reaches 60 k
engines:
ws: {}
scenarios:
- name: "Chat Connection"
engine: "ws"
flow:
- send: '{"type": "join", "room": "lobby"}'
- think: 300 # keep connection for 5 minTemplate 7: Microservice Chain Latency Test
Goal: Ensure end‑to‑end latency for order creation (API Gateway → Order Service → Payment Service → Inventory Service) stays below 1 s at the 99th percentile.
Test full‑chain latency for order creation:
- Chain: API Gateway → Order Service → Payment Service → Inventory Service
- Target: P99 < 1 s
- Tool: Jaeger + Locust
- Generate a test script that injects tracing headers and validates each segment's duration. import uuid
from locust import HttpUser, task
class OrderChainUser(HttpUser):
@task
def create_order(self):
trace_id = str(uuid.uuid4())
headers = {
"X-Request-ID": trace_id,
"Uber-Trace-ID": f"{trace_id}:1:1:1" # Jaeger format
}
self.client.post("/orders", json={"items": [...]}, headers=headers)
# Verify trace completeness in Jaeger
jaeger_resp = requests.get(f"http://jaeger:16686/api/traces/{trace_id}")
spans = jaeger_resp.json()["data"][0]["spans"]
total_latency = max(span["duration"] for span in spans) / 1e6 # seconds
assert total_latency < 1.0Template 8: Database Connection‑Pool Exhaustion Test
Goal: Simulate a Spring Boot application with HikariCP (maxPoolSize = 20) where 20 slow queries run concurrently; the 21st request should fail quickly (< 1 s).
Simulate DB connection‑pool exhaustion:
- Application: Spring Boot + HikariCP (maxPoolSize=20)
- Scenario: 20 slow queries (sleep 10 s) run simultaneously
- Verify: 21st request fails within 1 s
- Generate a JMeter script using JDBC Request. // JMeter BeanShell PreProcessor
import java.sql.*;
Connection conn = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://db:3306/test", "user", "pass");
Statement stmt = conn.createStatement();
stmt.execute("SELECT SLEEP(10)"); // slow query
} catch (SQLException e) {
if (e.getMessage().contains("timeout")) {
long duration = System.currentTimeMillis() - startTime;
if (duration < 1000) {
// Expected fast failure
}
}
} finally {
if (conn != null) conn.close();
}Template 9: CDN Cache‑Hit Rate Test
Goal: Ensure that a static asset (main.js) served via CDN receives fewer than 10 origin requests during a 1 000‑user concurrent load, i.e., cache‑hit rate > 99 %.
Validate CDN cache effectiveness for static resources:
- Resource: /static/main.js (Cache‑Control: max‑age=3600)
- Scenario: 1000 concurrent users
- Target: < 10 origin requests (hit rate > 99 %)
- Generate a k6 script that checks the X‑Cache response header. // k6 script
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = { vus: 1000, duration: '30s' };
export default function () {
const res = http.get('https://cdn.example.com/static/main.js');
check(res, { 'CDN hit': (r) => r.headers['X-Cache'] === 'HIT' });
sleep(1);
}Template 10: OAuth2.0 Authorization‑Code Performance Test
Goal: Complete the full OAuth2.0 authorization‑code flow (authorize → token → API call) in under 500 ms with 100 concurrent users per second.
Test OAuth2.0 authorization‑code flow performance:
- Flow: /authorize → /token → API call
- Target: Single flow < 500 ms
- Concurrency: 100 users/second
- Generate a Locust script that manages session state. class OAuthUser(HttpUser):
def on_start(self):
# Get authorization code
auth_resp = self.client.get("/oauth/authorize?client_id=test&redirect_uri=https://example.com/callback")
auth_code = extract_code_from_url(auth_resp.url)
# Exchange for token
token_resp = self.client.post("/oauth/token", data={
"grant_type": "authorization_code",
"code": auth_code,
"redirect_uri": "https://example.com/callback"
})
self.access_token = token_resp.json()["access_token"]
@task
def call_api(self):
self.client.get("/api/data", headers={"Authorization": f"Bearer {self.access_token}"})Template 11: Message‑Queue Backlog Test
Goal: Verify that a Kafka consumer can keep up with a production rate of 1 000 messages per second, processing each message in 10 ms, resulting in zero lag.
Validate Kafka consumer processing capacity:
- Topic: order-events
- Production rate: 1000 msg/s
- Consumer: single instance, 10 ms per message
- Target: No backlog (lag = 0)
- Generate a test script that monitors consumer lag. import time
from kafka import KafkaConsumer, KafkaProducer
def test_kafka_lag():
producer = KafkaProducer(bootstrap_servers='kafka:9092')
consumer = KafkaConsumer('order-events', bootstrap_servers='kafka:9092')
for i in range(1000):
producer.send('order-events', b'message')
producer.flush()
start_time = time.time()
for msg in consumer:
time.sleep(0.01) # 10 ms processing
if time.time() - start_time > 10:
break
lag = get_consumer_lag('order-events', 'test-group')
assert lag == 0Template 12: Multi‑Region Latency Test
Goal: Measure API health‑check latency from AWS us‑east‑1, eu‑west‑1, and ap‑southeast‑1, keeping the 95th percentile below 200 ms.
Test global user latency:
- Regions: AWS us-east-1, eu-west-1, ap-southeast-1
- Endpoint: GET /api/health
- Target: P95 < 200 ms per region
- Generate a distributed test plan using AWS Lambda. # AWS Lambda function
import boto3, requests, time
def lambda_handler(event, context):
region = event['region']
start = time.time()
resp = requests.get(f"https://{region}.api.example.com/health")
latency = (time.time() - start) * 1000
cloudwatch = boto3.client('cloudwatch', region_name=region)
cloudwatch.put_metric_data(Namespace='APIPerformance', MetricData=[{'MetricName': 'Latency', 'Value': latency, 'Unit': 'Milliseconds'}])
return {'latency_ms': latency}Template 13: Memory‑Leak Detection Test
Goal: Run a Node.js API for one hour at 100 RPS and ensure memory growth stays below 10 MB per hour.
Validate memory leak over prolonged run:
- Service: Node.js API
- Scenario: 1 hour, 100 RPS
- Monitor: Memory increase < 10 MB/hour
- Generate a test script that periodically samples heap usage. import psutil, time, requests
def test_memory_leak():
process = psutil.Process(get_nodejs_pid())
initial_memory = process.memory_info().rss / 1024 / 1024 # MB
start_time = time.time()
while time.time() - start_time < 3600:
requests.get("/api/data")
time.sleep(0.01) # 100 RPS
final_memory = process.memory_info().rss / 1024 / 1024
memory_growth = final_memory - initial_memory
assert memory_growth < 10Template 14: SSL/TLS Handshake Performance Test
Goal: Compare TLS 1.3 vs TLS 1.2 handshake times, ensuring TLS 1.3 completes in under 50 ms.
Test HTTPS handshake performance:
- Protocols: TLS 1.3 vs TLS 1.2
- Target: TLS 1.3 handshake time < 50 ms
- Tool: OpenSSL s_time for simulation
- Generate comparative test scripts. # TLS 1.3 test
openssl s_time -connect api.example.com:443 -www -tls1_3 -time 10
# TLS 1.2 test
openssl s_time -connect api.example.com:443 -www -tls1_2 -time 10
# Parse results
grep "Average" tls13.log | awk '{print $2}' # should be < 50Template 15: Containerized Application Resource‑Limit Test
Goal: Verify that a Docker container limited to 0.5 CPU cores actually uses roughly 50 % CPU while running a CPU‑intensive Fibonacci calculation.
Validate Docker CPU limit effect:
- Limit: CPU 0.5 core
- Application: CPU‑intensive task (Fibonacci)
- Target: Actual CPU usage ≈ 50 %
- Generate a test script that monitors cgroup stats. import subprocess, time
def test_cpu_limit():
# Start constrained container
subprocess.run(["docker", "run", "-d", "--cpus=0.5", "--name=cpu-test", "cpu-stress-image"])
start_time = time.time()
while time.time() - start_time < 60:
cpu_usage = float(subprocess.check_output([
"docker", "stats", "--no-stream", "--format", "{{.CPUPerc}}", "cpu-test"
]).decode().strip().rstrip('%'))
if abs(cpu_usage - 50) > 10:
raise AssertionError(f"CPU usage {cpu_usage}% not near 50%")
time.sleep(5)Template 16: Fault‑Injection Recovery Test
Goal: Kill the primary MySQL process, let Sentinel promote the replica, and ensure API error rate stays below 5 % with recovery time under 30 seconds.
Test API availability during DB master‑slave failover:
- Fault: kill primary MySQL process
- Recovery: Sentinel auto‑switch to replica
- Target: API error rate < 5 %, recovery time < 30 s
- Generate a Chaos Mesh experiment script. # chaos-mesh experiment
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
name: mysql-kill
spec:
action: pod-kill
mode: one
selector:
namespaces: ["prod"]
labelSelectors:
app: mysql-master
scheduler:
cron: "@every 5m"
---
# Verification script
import time, requests
def test_failover():
errors = 0
start_time = time.time()
while time.time() - start_time < 60:
try:
requests.get("/api/orders")
except:
errors += 1
time.sleep(1)
error_rate = errors / 60
assert error_rate < 0.05Usage Guide
Replace placeholders such as example.com and metric thresholds with values that match your actual system.
Combine multiple templates for complex scenarios (e.g., microservice chain + fault injection).
Integrate test results into Prometheus/Grafana for visualization.
Pair Grafana with k6 or Locust + InfluxDB to achieve a closed‑loop performance testing workflow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
