QA How-To
Cloud-Native Performance Testing Complete Guide (2026)
Use this cloud native performance testing complete guide to test Kubernetes scaling, service mesh latency, gRPC streams, and memory under realistic load.
25 min read | 3,380 words
TL;DR
A reliable cloud-native performance program starts with measurable SLOs, a production-shaped workload, controlled k6 execution, and synchronized Kubernetes telemetry. Test baseline capacity first, then autoscaling, mesh overhead, gRPC behavior, resilience, and endurance as separate experiments.
Key Takeaways
- Define service-level objectives and workload models before choosing a load tool.
- Test from controlled generators and correlate client results with Kubernetes and application telemetry.
- Separate steady load, scaling, resilience, streaming, and endurance questions into focused experiments.
- Verify autoscaling with pod, resource, latency, and queue evidence instead of pod count alone.
- Measure service mesh overhead with matched baselines and identical traffic paths.
- Use unique test data, bounded load, and explicit stop conditions to protect shared environments.
- Publish a reproducible report that connects user impact to infrastructure causes.
A cloud native performance testing complete guide must cover more than sending HTTP requests at Kubernetes. You need to prove how the whole system behaves when traffic changes: clients, gateways, service mesh proxies, application pods, queues, databases, autoscalers, and recovery controls. The useful result is not a maximum request count. It is evidence that user-facing objectives hold and that failures are understood.
This guide gives you a reproducible workflow using Kubernetes, Prometheus, and k6. You will establish a safe baseline, create a production-shaped workload, observe scaling, isolate mesh overhead, exercise gRPC and failure behavior, and run an endurance test. The examples are deliberately small enough for a test cluster, but the measurement method scales to larger platforms.
TL;DR
| Question | Experiment | Primary evidence |
|---|---|---|
| Can the release meet its SLO? | Steady baseline | p95 latency, error rate, throughput |
| Does Kubernetes add capacity in time? | Controlled traffic ramp | desired replicas, ready replicas, saturation |
| What does the mesh cost? | Matched mesh-on and mesh-off runs | latency distribution and proxy resources |
| Can streams remain healthy? | gRPC concurrency and duration | stream setup, messages, resets, flow control |
| Does the system degrade over time? | Endurance test | memory slope, GC, restarts, latency drift |
Start with one isolated question per run. Keep the application version, dataset, generator location, request mix, and observability window recorded. A test without that context is difficult to compare and easy to misread.
What You Will Build
By the end, you will have:
- A Kubernetes test target with explicit requests, limits, health probes, and autoscaling.
- A runnable k6 scenario with thresholds, tags, staged load, and realistic request checks.
- A measurement plan that connects k6 output to pod, node, proxy, and application metrics.
- Separate experiments for HPA response, service mesh cost, gRPC streams, resilience, and memory leaks.
- A repeatable report template with pass criteria and evidence links.
The goal is a small performance test system, not a single script. Every run should be traceable from a test identifier in the load generator to dashboards, logs, traces, and the deployed revision.
Prerequisites
Use a nonproduction Kubernetes cluster where you are authorized to create load. You need kubectl, Helm 3, Node.js 22 or another current LTS release, and k6. The examples use Kubernetes APIs that remain stable in current releases and avoid vendor-specific managed-service features.
kubectl version --client
helm version
k6 version
kubectl auth can-i create deployments -n perf
Create a namespace and confirm cluster metrics are available. HPA resource metrics normally come through Metrics Server. Prometheus is recommended for historical analysis, but it is not required to run the first smoke test.
kubectl create namespace perf --dry-run=client -o yaml | kubectl apply -f -
kubectl top nodes
kubectl get apiservice v1beta1.metrics.k8s.io
You also need a stable test dataset and a target endpoint. Never point the commands at production by changing a URL casually. Put environment allowlists, maximum virtual users, maximum duration, and an emergency stop owner in the test plan.
Step 1: Define the Cloud Native Performance Testing Complete Guide Scorecard
Write measurable acceptance criteria before generating load. Start from user outcomes, then attach diagnostic resource signals. A practical scorecard might require at least 99 percent successful requests, p95 latency below an agreed target, zero unexpected pod restarts, and recovery to normal latency within a fixed period after load falls. The values must come from your product SLOs and capacity plan, not from this example.
Create performance-objectives.yaml in your test project:
testId: checkout-baseline-001
service: checkout-api
environment: perf
revision: replace-with-git-sha
workload:
steadyRatePerSecond: 40
duration: 10m
readWriteRatio: 80:20
objectives:
httpRequestFailureRate: less-than-0.01
httpRequestDurationP95Ms: less-than-500
unexpectedRestarts: 0
readyReplicasAtSteadyState: at-least-2
guardrails:
maxVirtualUsers: 100
maxDuration: 30m
abortIfFailureRate: greater-than-0.10-for-2m
Distinguish a threshold from a diagnostic signal. Latency and error thresholds decide whether users received acceptable service. CPU, memory, throttling, queue depth, database connections, garbage collection, and proxy metrics explain why. Do not pass a release merely because CPU stayed low. Low CPU can accompany lock contention, downstream waits, or rejected work.
Verify: Review the file with the service owner and platform owner. Every objective must have a data source, unit, aggregation window, and named decision. Run kubectl config current-context and record the output with the scorecard so the target cannot be confused later.
Step 2: Deploy a Measurable Kubernetes Target
A performance target needs resource requests because HPA utilization uses them as a reference. It also needs readiness and liveness behavior that reflects the application. The following manifest assumes an existing checkout-api image and /health/ready, /health/live, and /api/products routes. Replace the image and port with your real service contract.
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkout-api
namespace: perf
spec:
replicas: 2
selector:
matchLabels:
app: checkout-api
template:
metadata:
labels:
app: checkout-api
spec:
containers:
- name: api
image: registry.example.com/checkout-api:2026.07.15
ports:
- name: http
containerPort: 8080
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: "1"
memory: 512Mi
readinessProbe:
httpGet:
path: /health/ready
port: http
periodSeconds: 5
livenessProbe:
httpGet:
path: /health/live
port: http
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: checkout-api
namespace: perf
spec:
selector:
app: checkout-api
ports:
- name: http
port: 80
targetPort: http
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: checkout-api
namespace: perf
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: checkout-api
minReplicas: 2
maxReplicas: 8
behavior:
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
Apply it, then wait for availability. Avoid testing during image pulls, migrations, cache warmup, or an incomplete rollout unless startup behavior is the specific experiment.
kubectl apply -f kubernetes/perf-target.yaml
kubectl rollout status deployment/checkout-api -n perf --timeout=180s
kubectl get pods,hpa -n perf
Verify: Both pods must show Ready, the deployment must show two available replicas, and kubectl describe hpa checkout-api -n perf must show a current CPU metric instead of <unknown>. If it is unknown, fix resource metrics before testing scaling.
Step 3: Create a Production-Shaped k6 Workload
Model arrival rate when the business workload is expressed as transactions per second. This prevents a slower system from silently reducing the rate, which can happen with a purely closed virtual-user model. Use a closed model when concurrent sessions are the actual controlled variable.
Save this as tests/checkout.js:
import http from 'k6/http';
import { check, sleep } from 'k6';
import exec from 'k6/execution';
const baseUrl = __ENV.BASE_URL;
if (!baseUrl) throw new Error('BASE_URL is required');
export const options = {
scenarios: {
checkout_traffic: {
executor: 'ramping-arrival-rate',
startRate: 5,
timeUnit: '1s',
preAllocatedVUs: 30,
maxVUs: 100,
stages: [
{ target: 20, duration: '2m' },
{ target: 40, duration: '10m' },
{ target: 0, duration: '2m' },
],
gracefulStop: '30s',
},
},
thresholds: {
http_req_failed: [{ threshold: 'rate<0.01', abortOnFail: true, delayAbortEval: '2m' }],
http_req_duration: ['p(95)<500'],
checks: ['rate>0.99'],
},
tags: { test_id: __ENV.TEST_ID || 'local-smoke' },
};
export default function () {
const user = `perf-${exec.scenario.iterationInTest % 10000}`;
const response = http.get(`${baseUrl}/api/products?limit=20`, {
headers: { 'X-Test-User': user },
tags: { operation: 'list_products' },
timeout: '10s',
});
check(response, {
'status is 200': (r) => r.status === 200,
'response is JSON': (r) =>
String(r.headers['Content-Type'] || '').includes('application/json'),
});
sleep(Math.random() * 0.5);
}
Checks validate individual responses. Thresholds decide the test exit status over aggregate metrics. Tags separate operations and attach the test ID. Add write operations only through supported test APIs and generate unique, traceable data so workers cannot overwrite one another.
Run a one-minute smoke against a port-forward before the full profile. Temporarily use environment variables to override your script profile if your repository supports that, or maintain a separate small smoke scenario.
kubectl port-forward -n perf service/checkout-api 8080:80
BASE_URL=http://127.0.0.1:8080 TEST_ID=checkout-smoke-001 k6 run tests/checkout.js
Verify: k6 must report successful checks, nonzero iteration and request counts, no dropped iterations, and a zero exit code. Confirm application logs contain the test user header or test ID. A smoke failure must be fixed before adding traffic.
Step 4: Run a Baseline and Correlate Telemetry
Run the generator from a stable location with enough CPU, memory, network bandwidth, and file descriptors. A laptop behind a variable VPN is useful for script development, not for a release baseline. Keep the generator outside the target pods so application contention does not steal load-generator capacity.
Start synchronized observation before the run:
kubectl get pods -n perf -l app=checkout-api -w
In another terminal, sample resource use and HPA state:
while true; do
date -u +%FT%TZ
kubectl top pods -n perf -l app=checkout-api
kubectl get hpa checkout-api -n perf
sleep 15
done
Then run the test with a unique ID and save the summary:
TEST_ID=checkout-baseline-001 \
BASE_URL=https://checkout.perf.example.com \
k6 run --summary-export=checkout-baseline-001.json tests/checkout.js
In Prometheus, inspect request rate, latency histograms, error codes, container CPU and memory, CPU throttling, restarts, ingress latency, proxy latency, database pools, and queue depth. Query raw counters with rate() over an appropriate window rather than graphing cumulative values. Use histogram buckets and histogram_quantile() only when bucket boundaries are suitable for your SLO.
Compare client and server views. Client duration includes network, gateway, mesh, application, and response transfer. Application handler duration usually covers less. The difference is a clue, not automatically mesh overhead. Align clocks and filter by test ID, route, revision, namespace, and status class.
Build a timeline before interpreting a bottleneck. Mark the test start, each workload stage, each deployment or HPA event, the first SLO breach, and the recovery point. Use the same UTC range on every dashboard. Averages across the full run can hide a short scaling failure, so inspect stage-level p50, p95, and p99 latency along with error classes and achieved throughput. Group failures by operation and status code instead of treating all errors as one rate.
Check telemetry quality as part of the experiment. Confirm scrape intervals are short enough to show the transition you care about, labels do not merge unrelated revisions, and dashboards do not silently downsample away a brief spike. Look for missing samples when pods restart. If trace sampling is enabled, record the policy and avoid assuming sampled traces represent exact traffic proportions. Logs should support diagnosis, but synchronous debug logging can change the result, so keep logging configuration identical across comparisons.
Use Little's Law as a reasonableness check when the system is stable: concurrency is approximately throughput multiplied by average time in the system. Large disagreement can reveal incomplete instrumentation, queued work outside the measured boundary, asynchronous completion, or units that were mixed. Treat this as a diagnostic check rather than a release threshold. The final report should distinguish observed facts, such as a queue rising before latency, from hypotheses, such as a database pool causing that queue.
Verify: Confirm k6 was not saturated by checking dropped iterations, achieved rate, and generator resources. Confirm dashboard traffic matches the k6 time window and approximate rate. Save the k6 JSON, dashboard links, deployment image digest, configuration, and observations together.
Step 5: Test Horizontal Pod Autoscaling
An HPA test asks whether new usable capacity arrives before user objectives fail. It does not merely ask whether replica count eventually increases. Begin from the minimum replica count, warm the application consistently, then raise traffic in deliberate stages.
Watch HPA decisions and pod readiness while the k6 ramp runs:
kubectl get hpa checkout-api -n perf -w
Capture scaling events separately:
kubectl get events -n perf \
--field-selector involvedObject.name=checkout-api \
--sort-by=.lastTimestamp
For each stage, record desired replicas, scheduled replicas, ready replicas, CPU utilization, pending time, image pull time, readiness delay, throughput, p95 and p99 latency, and errors. A rapid HPA decision cannot help if nodes lack capacity or readiness takes several minutes. Conversely, a temporary latency rise may reflect the chosen stabilization and rollout behavior rather than a broken HPA.
Run at least three shapes: gradual growth, a sharp but bounded spike, and a plateau long enough for stabilization. Reset the environment between comparable trials. Do not force replicas down immediately and call the next trial independent while caches, connections, and JVM or runtime state remain warm.
The detailed Kubernetes HPA load testing tutorial provides a focused experiment and interpretation checklist.
Verify: The achieved request rate must follow the intended ramp, ready replicas must converge on desired replicas, and latency plus errors must remain within the agreed scorecard or have a documented breach. After load falls, verify safe scale-down without request disruption.
Step 6: Isolate Mesh, gRPC, and Resilience Costs
Do not mix every cloud-native feature into one opaque benchmark. Use paired experiments that change one factor at a time. For mesh overhead, compare identical revisions and traffic with equivalent routing, once through sidecars or ambient data plane and once through an approved mesh-free baseline. Keep TLS, connection reuse, payloads, retries, telemetry sampling, and generator placement visible because each can change results.
| Experiment | Hold constant | Change | Watch |
|---|---|---|---|
| Mesh comparison | Workload, revision, nodes, data | Data-plane path | Client latency, proxy CPU, resets |
| gRPC streaming | Message size, server, network | Streams and message rate | Setup latency, stream duration, resets |
| Pod termination | Load and replica count | One controlled deletion | Errors, reconnects, recovery time |
| Dependency delay | Request mix and capacity | Bounded injected latency | Timeout budget, retries, queue growth |
For gRPC, use a protocol-aware load tool and real protobuf definitions. Measure connection setup separately from long-lived stream health. Count messages, canceled streams, status codes, reconnects, and flow-control stalls. HTTP request averages cannot represent a bidirectional stream. Follow the gRPC streaming performance test guide for a complete protocol-specific setup.
For resilience, begin with one reversible failure in an isolated environment. Delete one pod or apply an approved fault while load is steady:
POD=$(kubectl get pod -n perf -l app=checkout-api -o jsonpath='{.items[0].metadata.name}')
kubectl delete pod -n perf "$POD" --wait=false
kubectl get pods -n perf -l app=checkout-api -w
Observe readiness removal, endpoint propagation, in-flight failures, retry amplification, replacement scheduling, and recovery. Stop if guardrails are breached. Never hide errors with unbounded retries, because retries add load exactly when capacity is impaired.
Use the service mesh latency measurement tutorial to design matched baselines.
Verify: Repeat each pair enough times to distinguish a consistent effect from ordinary run variation. Report distributions and resource cost, not one average. For the pod deletion, prove the service returned to the scorecard and that no unexpected duplicate write occurred.
Step 7: Run an Endurance Test and Publish the Decision
An endurance test holds representative traffic long enough to reveal retained memory, connection leaks, queue accumulation, log growth, token refresh defects, and periodic jobs. Duration should cover relevant application cycles. A thirty-minute run is not a universal soak test, and a twenty-four-hour run is wasteful if the suspected leak is visible sooner.
Record memory as a time series per pod and correlate it with allocation rate, garbage collection, heap after collection, request count, active connections, cache size, and restarts. Kubernetes working set alone cannot prove a heap leak. A rising process can reflect a bounded cache or filesystem behavior. The decisive pattern is retained growth that fails to settle under a stable workload and is supported by runtime evidence.
Use a constant-arrival-rate scenario based on the validated baseline. Keep deployment changes, autoscaler changes, backups, and unrelated jobs documented. Periodically sample state without restarting the pods. At the end, stop traffic and observe whether memory returns to an expected idle band. Capture a heap profile only through approved tooling because it can be expensive and may contain sensitive data.
Divide the endurance run into fixed analysis windows. For each window, record completed transactions, p95 latency, errors, pod count, restarts, heap after collection, resident memory, active connections, and queue depth. Normalize retained growth by completed work when that relationship is useful. A raw memory increase of the same size can mean very different things at ten thousand and ten million completed transactions. Also inspect whether growth occurs on every pod or only the pod receiving a specific route, tenant, or scheduled task.
Plan the stop decision before the run. Stop immediately for data corruption, uncontrolled retry amplification, exhausted shared dependencies, or a guardrail breach. Stop as inconclusive if generator saturation, telemetry gaps, or an unrelated rollout invalidates the controlled conditions. Otherwise continue until you cover the planned cycle or gather enough repeated evidence to accept or reject the suspected degradation. This prevents a team from extending a test simply because the graph looks interesting.
The long-running load test memory leak guide explains slope analysis and confirmation.
Publish one decision record containing:
- Test ID, question, owner, environment, revision, and timestamps.
- Workload model, dataset, generator resources, and achieved load.
- Pass criteria with actual results and confidence limitations.
- Timeline linking user metrics to pods, nodes, proxies, and dependencies.
- Bottleneck evidence, rejected explanations, and follow-up owners.
- Raw artifacts, queries, dashboards, configuration, and rerun command.
Verify: Another engineer must be able to rerun the test from the record without guessing. The decision must say pass, fail, or inconclusive. If inconclusive, name the missing evidence and the next bounded experiment.
Troubleshooting
HPA shows <unknown> CPU -> Confirm Metrics Server is healthy, pods have CPU requests, and resource metrics are returned by kubectl top pods. Do not tune HPA from missing data.
k6 reports dropped iterations -> The generator could not start iterations at the requested arrival rate. Increase preallocated VUs within guardrails, inspect max VUs and generator capacity, then rerun. Treat achieved load as lower than planned.
Client latency is high but handlers look fast -> Inspect DNS, connection setup, TLS, ingress, proxy, response transfer, and generator saturation. Align timestamps and use traces or route-level histograms before assigning blame.
More replicas do not increase throughput -> Check downstream capacity, shared locks, database pools, queues, node saturation, throttling, and load-balancer distribution. Scaling a stateless tier cannot remove every bottleneck.
Failures appear only at high concurrency -> Look for connection limits, ephemeral ports, file descriptors, thread pools, retry storms, and shared test accounts. Reduce concurrency to find the boundary, then change one limit or design factor per trial.
Memory rises during the soak -> Compare heap after collection and retained objects with request count. Rule out bounded caches and native buffers. Reproduce the slope, capture approved profiles, and verify a fix with the same workload.
The Complete Series
- Load test Kubernetes Horizontal Pod Autoscaling: Prove that desired and ready capacity arrive before the user SLO fails.
- Measure service mesh latency overhead: Build matched experiments that isolate proxy and data-plane cost.
- Performance test gRPC streaming services: Measure stream setup, messages, flow control, resets, and recovery.
- Detect memory leaks in long-running load tests: Separate retained growth from healthy caches and runtime behavior.
Together these tutorials turn the pillar workflow into focused, reproducible experiments. Start with the risk most likely to violate your service objective, not the feature that is easiest to demonstrate.
Where To Go Next
First automate the baseline in CI as a small, stable test, while keeping heavier scaling and endurance runs scheduled or manually approved. Store thresholds and workload code with the service, but keep environment capacity and secrets outside the script. Add a release comparison only after the baseline is reproducible.
Next, choose one deep dive from the complete series. Test HPA if traffic changes rapidly, mesh overhead if the data plane changed, gRPC if streams carry critical work, or endurance if memory and connections drift. Expand coverage only when each experiment retains a clear question and safe stop conditions.
Interview Questions and Answers
Q: How do you design a cloud-native performance test?
Start with a user-facing SLO and a production-shaped workload. Run from a controlled generator, tag the traffic, and correlate client results with application and Kubernetes telemetry. Change one major factor per experiment and publish reproducible evidence.
Q: Why are CPU and memory not sufficient pass criteria?
They are diagnostic resource signals, not direct user outcomes. A service can fail from locks, queues, downstream waits, or connection exhaustion while CPU remains low. Latency, errors, and completed business work decide the user result.
Q: How do you validate an HPA under load?
I track HPA desired replicas, scheduling, readiness, achieved load, latency, and errors on one timeline. I test gradual and sharp ramps, then verify scale-down. Replica growth alone is not a pass if capacity arrives too late.
Q: How do you measure service mesh overhead?
I run matched mesh-on and approved mesh-off experiments with the same workload, revision, placement, and protocol behavior. I compare latency distributions, proxy resources, resets, and throughput across repeated runs. I report limitations instead of subtracting unrelated averages.
Q: What is different about gRPC streaming tests?
Streams can remain open and carry many messages, so request count is insufficient. I measure stream setup, concurrent streams, message rate and latency, status codes, flow control, cancellations, reconnects, and resource use.
Q: How do you identify a memory leak?
I hold workload stable and examine retained memory over time, especially heap after collection. I correlate growth with requests, caches, connections, GC, and restarts, then inspect retained objects with approved profiling. A rising container graph alone is not proof.
Q: How do you keep performance testing safe?
I use an authorized environment, allowlisted targets, bounded users and duration, stop thresholds, named owners, and isolated data. I verify the Kubernetes context before running and never embed production credentials in scripts.
Best Practices
- Keep one test question and one decision per experiment.
- Version workload code, manifests, dashboards, and scorecards with the release context.
- Warm caches consistently and document whether warm or cold behavior is under test.
- Use unique data ownership and idempotent cleanup for every run.
- Validate generator capacity and achieved load before blaming the target.
- Compare distributions and timelines, not isolated averages.
- Separate client SLOs from diagnostic platform signals.
- Repeat comparative tests and disclose ordinary variation.
- Preserve raw results and exact queries behind every conclusion.
- Stop automatically when safety guardrails or severe error thresholds fail.
Common Mistakes
- Starting with maximum load before validating a smoke and baseline.
- Treating virtual users as requests per second without understanding the executor model.
- Declaring HPA success because the replica count increased.
- Changing workload, version, placement, and mesh policy in one comparison.
- Ignoring generator CPU, network, dropped iterations, and clock alignment.
- Using shared accounts or records that create artificial locks and conflicts.
- Increasing timeouts until failures disappear without finding the bottleneck.
- Calling any rising memory graph a leak without runtime evidence.
- Publishing screenshots without raw data, queries, context, or rerun commands.
Cloud Native Performance Testing Complete Guide Conclusion
Cloud-native performance testing succeeds when it connects a realistic workload to a measurable user objective and a complete diagnostic timeline. Establish the baseline first. Then test autoscaling, mesh behavior, streaming, resilience, and endurance as controlled experiments rather than one giant stress run.
Use the scorecard and k6 workflow in this guide for your first reproducible run. Preserve the results, choose the highest-risk deep dive from the complete series, and turn each finding into a capacity, reliability, or release decision.
Interview Questions and Answers
How would you create a cloud-native performance testing strategy?
I begin with business transactions and user-facing SLOs, then model production arrival patterns, data, and protocols. I establish a repeatable baseline before isolating scaling, mesh, resilience, streaming, and endurance risks. Every run includes safety limits, synchronized telemetry, and a reproducible decision record.
What is the difference between a load test and a stress test?
A load test verifies behavior at expected and planned traffic against defined objectives. A stress test deliberately moves beyond expected capacity to find limits and failure modes. I establish a safe baseline before stress testing and use explicit stop conditions.
Why use an arrival-rate executor?
It controls the rate at which iterations start, so target slowdown does not automatically reduce offered work. That matches workloads expressed as transactions per second. I still verify dropped iterations and generator capacity because the configured rate may not be achieved.
How do you correlate k6 and Kubernetes metrics?
I use a unique test ID, synchronized clocks, recorded timestamps, and consistent route or operation tags. I compare the client timeline with HPA, pod, node, proxy, runtime, and dependency signals. I preserve dashboard queries and raw results with the deployed revision.
What can prevent HPA from improving performance?
Missing resource requests, delayed metrics, slow scheduling, image pulls, readiness time, node capacity, and scale policies can delay usable pods. Shared downstream bottlenecks can also cap throughput even after replicas grow. I measure each transition rather than assuming the autoscaler is the only factor.
How would you test graceful behavior during pod termination?
I apply steady bounded load, delete one pod in an isolated environment, and observe readiness removal, endpoint propagation, in-flight requests, retries, duplicate writes, replacement readiness, and recovery time. The test passes only if user objectives and data integrity meet the scorecard.
How do you prove a memory leak under load?
I reproduce retained growth under stable work and inspect heap after collection or equivalent runtime evidence. I correlate it with request count, caches, connections, allocation, GC, and restarts. Then I identify retained objects and rerun the same workload after the fix.
Frequently Asked Questions
What is cloud-native performance testing?
It evaluates user-facing performance across distributed application and platform layers such as gateways, service meshes, Kubernetes workloads, autoscalers, queues, and dependencies. It combines controlled load with synchronized application and infrastructure telemetry.
Which tool should I use for Kubernetes load testing?
k6 is a strong choice for HTTP workloads and scripted thresholds, while protocol-specific tools may be better for gRPC or specialized traffic. Tool choice follows the protocol and workload model, not Kubernetes itself.
Should performance tests run inside Kubernetes?
They can, but generators must be isolated from target contention and have measured capacity. External generators include ingress and network paths, while in-cluster generators help isolate internal service behavior. Record the placement in every result.
How do I know whether HPA passed a load test?
Confirm that usable ready capacity arrived while latency, errors, and completed throughput met the scorecard. Desired replica count alone is insufficient because scheduling, startup, readiness, and downstream bottlenecks affect user results.
How long should an endurance test run?
Run long enough to cover the suspected accumulation and relevant periodic cycles. Choose duration from evidence such as memory slope, token lifetime, cache behavior, or scheduled jobs rather than using a universal number.
How do I compare service mesh latency?
Use repeated matched tests that hold workload, revision, placement, protocol, and dataset constant while changing only the approved data-plane path. Compare latency distributions, throughput, errors, and proxy resource cost.
What metrics matter most in cloud-native performance tests?
Start with user latency, error rate, achieved throughput, and completed business transactions. Use pod, node, proxy, runtime, queue, and dependency metrics to explain those outcomes.