Describe the risk first, then choose the smallest test layer that provides useful evidence. A tool name without an oracle or failure model is not a test strategy.
Question set
13 detailed answers
01Describe client-server architecture. Why can't you rely on client-side validation alone?
junior
Short answer: The client (browser, mobile app) sends a request, the server processes it and returns a response — the request/response model over HTTP. You can't rely on client-side validation because the client is fully under the user's control: the form can be bypassed via curl, Postman, or DevTools and any data sent to the server. So the server must validate itself, and QA tests both layers independently.
In depth:
- Client — renders the UI, does first-pass validation for convenience (fast feedback, less traffic), holds the token.
- Server — the source of truth: checks permissions, validates the body, writes to the DB. It's the only layer you can trust.
- What QA does — doesn't just click the UI but hits the API directly, bypassing the client: sends empty/invalid fields, someone else's
id, injections — and checks the server rejected them (400/403) rather than saving them.
CLIENT SERVER
┌────────┐ request (HTTP) ┌─────────┐
│ UI │ ─────────────────► │ API │
│ ✔ UX │ │ ✔ manda-│
│ valid. │ ◄───────────────── │ tory │──► DB
└────────┘ response │ valid. │
▲ can be bypassed: └─────────┘
└── curl / Postman / DevTools
⚠️ Common mistake: assuming that because the Submit button is disabled on the form, invalid data never reaches the server. The UI is bypassed in a second — a robust system validates everything server-side.
02Name the main HTTP methods. Which of them are idempotent?
middle
Short answer: The main methods are GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS. Idempotent ones are GET, PUT, DELETE, HEAD, OPTIONS (repeating the request doesn't change state beyond the first call). POST is not idempotent — a repeated call may create another resource or perform the action a second time. PATCH is not guaranteed idempotent: it depends on the implementation.
In depth:
Idempotency is a property where N identical requests leave the server in the same state as a single one. It's about the server-side side effect, not the response body.
| Method | Purpose | Idempotent |
|---|---|---|
| GET | fetch a resource | yes |
| HEAD | like GET, no body | yes |
| OPTIONS | which methods are allowed | yes |
| POST | create / perform an action | no |
| PUT | replace the whole resource | yes |
| PATCH | partial update | not guaranteed |
| DELETE | delete the resource | yes |
DELETE is idempotent by effect: the resource is gone after the first call and stays gone — even if the second call returns 404 (that's fine, state didn't change).
⚠️ Common mistake: calling PATCH idempotent by analogy with PUT. PATCH {"balance": +10} on retry adds another 10 — whereas PUT sets an absolute value and is therefore idempotent. Check edge cases against MDN / RFC 9110.
03What is the difference between PUT and PATCH?
middle
Short answer: PUT replaces the whole resource — you send the full representation and the server overwrites the object with it. PATCH updates partially — you send only the fields being changed. PUT is always idempotent; PATCH is not guaranteed to be.
In depth:
- PUT — full replacement. The body must contain the entire object. A missing field is treated as "this field is absent" — the server may null it out.
- PATCH — a delta. You send only what you're changing; the rest stays as it was.
- Link to idempotency. A repeated identical PUT sets the same absolute state → idempotent. PATCH is idempotent only if the operation is absolute (
set city=Moscow), and NOT idempotent if it's relative (increment).
PUT /users/42 → body: {name, email, city} — the whole object
PATCH /users/42 → body: {city: "Moscow"} — the delta only
What to test: send a PUT with some fields omitted and check whether they got nulled (a common bug); send the same PATCH twice and verify the state matches.
⚠️ Common mistake: sending PUT with a partial body expecting a partial update. By spec PUT is a replacement: missing fields can be lost.
04What is the difference between 401 and 403?
middle
Short answer: 401 Unauthorized — the server doesn't know who you are: credentials weren't sent, or the token is expired/invalid. 403 Forbidden — the server knows who you are, but you don't have permission for this action. In one line: 401 is "not logged in," 403 is "logged in, but not allowed."
In depth:
This is exactly the authentication-vs-authorization pair, split across status codes:
| Code | Meaning | Cause | What the client does |
|---|---|---|---|
| 401 | not authenticated | missing/broken/expired token | log in, refresh token |
| 403 | no permission | role/scope doesn't allow it | login won't help — needs rights |
Scenarios:
- Calling a private endpoint with no
Authorizationheader at all → 401. - A regular user hitting
/adminwith a valid token → 403. - The token existed but expired → 401 (the client should refresh and retry).
⚠️ Common mistake: returning 403 for an expired token. The client will assume it lacks permissions and won't refresh — when re-authenticating (401) was all it needed. For security, APIs sometimes deliberately return 404 instead of 403 to hide a resource's existence — worth calling out separately.
05What is the difference between 502 and 504, and when do you see them?
middle
Short answer: Both 502 and 504 are returned by a proxy/gateway (nginx, load balancer, API gateway) when the problem is in the upstream behind it. 502 Bad Gateway — the upstream answered, but with something invalid (garbage, a dropped connection, a crashed process). 504 Gateway Timeout — the upstream didn't answer in time; the gateway gave up waiting.
In depth:
It matters to tell the whole 5xx cluster apart:
| Code | Who's at fault | Symptom |
|---|---|---|
| 500 | the server itself | unhandled exception in code |
| 502 | upstream behind proxy | returned an invalid response |
| 503 | the service | temporarily unavailable (overload, deploy) |
| 504 | upstream behind proxy | didn't answer within the timeout |
CLIENT ──► PROXY / GATEWAY ──► UPSTREAM (app)
(nginx, LB)
│ upstream sent garbage → 502
│ upstream silent, timeout → 504
As QA: seeing 502/504, don't file a front-end bug — look at the upstream and proxy logs. 504 is often a slow request / gateway timeout, 502 is a crashed or restarting service.
⚠️ Common mistake: swapping the pair — "502 is a timeout." A timeout is 504; 502 is an invalid response from a live-but-broken upstream.
06What are the HTTP status code classes?
junior
Short answer: Five classes by the first digit: 1xx — informational, 2xx — success, 3xx — redirects, 4xx — client error, 5xx — server error. The key boundary is 4xx (the client's fault: bad request, no permission) vs 5xx (the server's fault).
In depth:
| Class | Meaning | Common example |
|---|---|---|
| 1xx | info, interim response | 100 Continue |
| 2xx | success | 200 OK, 201 Created, 204 No Content |
| 3xx | redirect | 301 Moved, 302 Found, 304 Not Modified |
| 4xx | client error | 400, 401, 403, 404, 429 |
| 5xx | server error | 500, 502, 503, 504 |
Worth knowing specifically:
- 201 Created — a resource was created successfully (typical POST response).
- 204 No Content — success with no body (often DELETE).
- 304 Not Modified — the cache is fresh, no body will be sent.
- 429 Too Many Requests — a rate limit kicked in.
⚠️ Common mistake: returning 200 with a {"error": ...} body. The status is part of the contract: an error must travel under its own code (4xx/5xx), or clients and monitoring will count the request as successful.
07How does REST differ from SOAP, and why do banks still use SOAP?
middle
Short answer: REST is an architectural style over HTTP: resources by URL, standard methods, stateless, usually JSON. SOAP is a strict protocol: an XML envelope of fixed structure, a WSDL contract, its own stack of standards (WS-Security and others). SOAP is heavier but survives in banks and enterprise thanks to rigid contracts, built-in security, and a mass of legacy integrations no one will rewrite.
In depth:
| Criterion | REST | SOAP |
|---|---|---|
| What it is | architectural style | protocol |
| Transport | HTTP only | HTTP, also SMTP, MQ |
| Format | usually JSON (XML possible) | always an XML envelope |
| Contract | OpenAPI (optional) | WSDL (strict) |
| Security | HTTPS + tokens | WS-Security at message level |
| Style | light, flexible | strict, verbose |
Why banks keep SOAP: WSDL gives a machine-verifiable contract, WS-Security and transactionality are in the standard, and replacing working interbank integrations is a risk that doesn't pay off.
⚠️ Common mistake: calling REST a protocol (it's a style) or equating REST = JSON. REST isn't tied to a format — JSON just became the de-facto choice.
08How do you test an API endpoint without a UI? What exactly do you check in Postman?
middle
Short answer: I hit the endpoint directly from Postman/curl and check not just the status but the body, schema, headers, authorization, negative scenarios, and response time. No UI is needed — the API is tested as a standalone contract.
In depth:
- Status code — 200/201/204 on success, expected 4xx on invalid input.
- Body and schema — fields present, types correct, no extra/leaked fields; I validate against a JSON schema, not by eye.
- Headers —
Content-Type, caching,Locationon 201. - Authorization — no token → 401; someone else's token → 403.
- Negative cases — missing required param, wrong type, duplicate, boundary values.
- Performance — response time within SLA.
- Chaining — pull a token/
idfrom one response and feed it into the next request.
// Postman: test the response + save the token for the next request
pm.test("status 200", () => pm.response.to.have.status(200));
pm.test("has token", () => pm.expect(pm.response.json().token).to.exist);
pm.collectionVariables.set("token", pm.response.json().token);
// later in the header: Authorization: Bearer {{token}}
⚠️ Common mistake: stopping at assert 200. A service can return 200 with an empty/broken body or extra fields — without schema and negative checks that slips right through.
10What is the TCP handshake and how does HTTPS differ from HTTP?
middle
Short answer: The TCP handshake is a three-step SYN → SYN-ACK → ACK exchange by which client and server establish a connection before any HTTP data is sent. HTTPS is HTTP over TLS: after the TCP handshake comes a TLS handshake (certificate check, key exchange), and from then on all HTTP traffic is encrypted.
In depth:
- TCP handshake — ensures both sides are ready:
SYN(client),SYN-ACK(server),ACK(client). Only then is the connection open. - TLS handshake (HTTPS only) — on top of TCP: the server sends its certificate, the parties agree on keys, encryption turns on.
- HTTP vs HTTPS — HTTP sends data in plaintext (port 80); HTTPS sends it encrypted (port 443), protected against interception and tampering.
TCP handshake TLS handshake (HTTPS only)
Client ── SYN ─────►
◄─ SYN-ACK ── Server
── ACK ──────►
── ClientHello ─────►
◄─ certificate, keys ─ Server
══ encrypted HTTP ════►
⚠️ Common mistake: lumping the TCP and TLS handshakes into one. They're two separate stages: the TCP connection is established first, and only then TLS on top of it. HTTPS adds the second step without replacing the first.
12What do an HTTP request and response consist of?
junior
Short answer: An HTTP request is a request line (method, path, version), headers, and an optional body. An HTTP response is a status line (version, status code, reason), headers, and a body. Both separate headers from body with a blank line.
In depth:
- Request line — method (
GET/POST), path (/users/42), version (HTTP/1.1). - Headers — metadata:
Host,Authorization,Content-Type,Accept. - Body — the request payload (JSON on POST/PUT); usually empty on GET.
- Status line (response) — version, code (
200), reason (OK).
POST /api/login HTTP/1.1 ← request line
Host: api.example.com ← headers
Content-Type: application/json
← blank line
{ "email": "a@b.io", "pwd": "…" } ← body
HTTP/1.1 200 OK ← status line
Content-Type: application/json ← headers
{ "token": "eyJhbGciOi…" } ← body
This is the foundation for reading the Network tab and working in Postman: you see exactly these parts there.
⚠️ Common mistake: confusing headers and body — e.g. sending the token in the body instead of the Authorization header, or looking for POST data in the query string rather than the body.
13How do you test that a payment API is safe under request retries?
senior
Short answer: I verify the idempotency key: the client sends a unique key in a header (e.g. Idempotency-Key), and a repeated POST with the same key doesn't create a second payment but returns the first one's result. I test duplicates, network drops, and parallel retries — that's exactly where double charges surface.
In depth:
- Duplicate request — two identical POSTs with one key → one payment, the second response identical to the first.
- Drop after the charge — money was charged but the response never arrived; the client retries with the same key → no second charge.
- Parallel retries — two requests with one key at the same time (a race) → exactly one payment is created, the second waits for / receives the same result.
- Different key — same payment but a new key → this is a new payment (confirming the key actually matters).
- DB-side check — after a burst of retries the table holds exactly one transaction.
Client API
│ POST /pay Key: abc-123 ──► charge ✔, response lost ✗
│ (timeout, network dropped)
│ POST /pay Key: abc-123 ──► same key → returns the prior
│ result, NO second charge
⚠️ Common mistake: assuming "POST will sort itself out" or that a unique order_id in the body is enough. Without an explicit idempotency key checked on the server, a retry after a network drop yields a double charge — a classic fintech incident.
Source notes
References and review policy
RecallDeck’s interview answers are editorial material, reviewed against maintained official documentation where a primary reference is available. Tool selections use direct provider links and contain no affiliate placements. Features can change after the review date.
From reading to recall
Practice the full interview loop.
RecallDeck schedules the concepts you miss and keeps coding, design, and behavioral fundamentals available when the interviewer changes direction.