QA & Testing · Guide

Performance & Security Testing

The non-functional half: what breaks under load, where the bottleneck actually is, and the security checks QA owns.

— min read QA & Testing

Fast Enough, Safe Enough

Functional testing asks whether the feature works. Non-functional testing asks whether it still works at 10,000 users, at 3am after six days of uptime, and when someone is deliberately attacking it.

These are the tests most often skipped and most expensive to skip, because their failures arrive all at once, in production, at the worst possible moment — a launch, a sale, a news cycle.

Load Testing

The words are not interchangeable, and using the wrong one leads to testing the wrong thing.

TestQuestion
LoadDoes it hold up at expected traffic
StressWhere does it break, and how
SpikeWhat happens when traffic multiplies in seconds
SoakDoes it survive days — leaks, growing queues, full disks
ScalabilityDoes adding capacity actually help
// k6: ramp up, hold, and fail the run on the percentile, not the mean
export const options = {
  stages: [
    { duration: '2m', target: 200 },   // ramp
    { duration: '5m', target: 200 },   // hold
    { duration: '2m', target: 0 },     // ramp down
  ],
  thresholds: {
    http_req_duration: ['p(95)<500'],
    http_req_failed:   ['rate<0.01'],
  },
};
Never report an average response time. Averages hide the tail: a 200ms mean can contain 5% of users waiting four seconds. Report p95 and p99 — those are real people, and they are the ones who leave.

A number without conditions is meaningless. "The API handles 2,000 requests per second" needs the hardware, the data volume, the mix of endpoints and the cache state, or it cannot be compared with anything — including itself next month.

Finding the Bottleneck

A load test that reports "it got slow" is only half the job. The useful output identifies the resource that ran out, and the shape of the graph usually says which.

SymptomUsual cause
Latency climbs while CPU stays lowWaiting — locks, a saturated pool, a slow dependency
Throughput plateaus, latency rises linearlyA queue: capacity reached, work backing up
Errors appear at a specific concurrencyA connection or thread pool limit
Slow degradation over hoursA leak — memory, file handles, unclosed connections
Database CPU pinnedMissing index, or N+1 queries under load
Test against production-shaped data. A query that is instant over a thousand seeded rows and catastrophic over ten million is the single most common performance surprise, and a clean test database hides it completely.

Security Testing In QA

Deep security work belongs to specialists, but a QA team can catch a surprising share of real issues by testing the boundaries deliberately rather than only the happy path.

CheckWhat you are looking for
AuthorisationChange an id in the URL — do you see someone else's data
Input handlingScript tags, quotes and huge payloads reflected or accepted
Rate limitsCan login be attempted a thousand times
Error messagesStack traces, SQL and internal hostnames leaking to users
Session handlingDoes logout end the session everywhere it should
DependenciesKnown-vulnerable packages, caught by a scanner in CI

The most valuable of these is broken access control — changing an identifier to reach data belonging to another account. It is consistently the most common serious web vulnerability, it needs no tooling to find, and automated functional tests never look for it because every test signs in as the right person.

Only test systems you are authorised to test, in an environment agreed with whoever owns it. Run destructive or high-volume checks against staging, not production.

Interview Questions

Load, stress, spike or soak?

Load checks expected traffic, stress finds the breaking point, spike checks a sudden multiplication of traffic, and soak runs for days to expose leaks and slow degradation.

Why report percentiles rather than averages?

Averages hide the tail. A 200ms mean can contain 5% of users waiting four seconds — and those users are the ones who abandon. p95 and p99 describe real experience.

Latency rises but CPU stays low. What does that suggest?

Waiting rather than computing — lock contention, an exhausted connection pool, or a slow downstream dependency. Adding CPU will not help.

Why does test data volume matter?

Queries that are instant over a thousand seeded rows can be catastrophic over ten million. A small clean database hides the most common performance defect there is.

What security issue can QA reliably catch?

Broken access control — changing an id in a URL or payload to reach another account's data. It is the most common serious web flaw and normal functional tests never look for it.

What makes a performance number meaningful?

Its conditions: hardware, data volume, endpoint mix, cache state and concurrency. Without them the figure cannot be compared to anything, including a later run of the same test.

Quick Quiz

1. A soak test looks for…
2. The right headline latency metric is…
3. Latency climbing while CPU stays low suggests…
4. Changing an id in a URL to see another user's data tests…
5. A performance figure without conditions is…