Skip to main content

Backend — Interview Questions

Common questions with model answers. Use the language switcher (top-right) for Bahasa Indonesia.

HTTP & API design

What is the difference between PUT and PATCH?

  • PUT — replace the resource (or its representation) entirely. Idempotent.
  • PATCH — apply a partial update. Not strictly required to be idempotent (depends on the patch spec).

When would you return 200 vs 201 vs 204?

  • 200 OK — generic success with a body.
  • 201 Created — a new resource was created (return Location header).
  • 204 No Content — success, intentionally no body (e.g., DELETE).

What does "idempotent" mean? Why does it matter for APIs?

Calling the same request multiple times produces the same server state as calling it once. Matters because networks retry — a non-idempotent endpoint that gets retried can double-charge a customer or create duplicate orders.

For unsafe operations (POST), the standard mitigation is an Idempotency-Key header — the server records the result for that key and returns the same result on retries.

Databases

What does an index do? When would you NOT add one?

An index is an auxiliary data structure (often a B-tree) that lets the DB find rows by an indexed column without scanning the whole table.

You don't want one when:

  • The table is tiny (a full scan is cheap).
  • The column has very low cardinality and queries don't filter on it usefully.
  • Write throughput matters more than read latency — every insert/update has to maintain the index.

Explain ACID

  • Atomicity — a transaction is all-or-nothing.
  • Consistency — the DB moves from one valid state to another (constraints/triggers honored).
  • Isolation — concurrent transactions don't see each other's intermediate state.
  • Durability — once committed, data survives crashes.

LEFT JOIN vs INNER JOIN

  • INNER JOIN — only rows that match in both tables.
  • LEFT JOIN — all rows from the left table; matched columns from the right table or NULL.

What is the N+1 query problem?

You fetch a list of N parents (1 query), then loop and fetch each parent's children with a separate query (N queries) — total N+1. Fix with a join, a batched IN query, or your ORM's eager-loading (include, with).

Architecture & scaling

What problem does a message queue solve?

Decouples producers and consumers. Producers drop work onto the queue; consumers pull and process at their own rate. Smooths spikes, enables retries, lets services fail independently. Trade-off: eventual consistency and operational complexity.

Sessions vs JWT

  • Server-side sessions — server stores session state; client sends a session ID cookie. Easy to revoke. Needs a session store.
  • JWT — signed token carries claims; server verifies the signature without a lookup. Scales horizontally but revocation is hard (you need a denylist or short expiry + refresh tokens).

How would you make a service horizontally scalable?

  • Statelessness — push state to a DB / cache / queue.
  • Sticky-session avoidance — use a shared session store (Redis) or stateless auth (JWT).
  • Connection pools sized to the DB's limits, not the service's.
  • Caching at the right layer (CDN, app cache, DB cache).
  • Async work via queue.

Behavioral

Walk me through a recent backend project

At LinkAja I supported the TCash → LinkAja core migration — moving partner credentials from the legacy core system to the new one without requiring any change on the partner side. That meant designing a shim that recognized old credentials and routed them correctly during the transition, coordinating cut-over windows with each partner, and adding telemetry to monitor for partner-side failures. Migrated 100+ partners without a major incident.

Tell me about a time you had to debug a tricky production issue

When a partner reported failed transactions, the workflow was: reproduce with their payload → check Grafana logs around the timestamp → identify whether it's an integration error (partner-side: wrong payload, expired creds, network) or a system error (our side). If integration, I documented the fix and walked the partner through it; if system, I raised it to the system analyst with the reproduction.

Why backend?

I started as a PHP programmer at AGIT working on integration. I moved into BAU Integration at LinkAja where I worked directly with system analysts on integration flows. The backend / API side of products is where I find the cleanest problem statements: clear inputs, clear outputs, measurable correctness.

Behavioral (Bahasa Indonesia)

Ceritakan project backend yang baru kamu kerjakan

Di LinkAja saya terlibat di core migration TCash → LinkAja — memindahkan credentials partner dari core lama ke yang baru tanpa perubahan dari sisi partner. Saya mendesain shim untuk mengenali credential lama dan merutekannya dengan benar selama transisi, mengkoordinasikan cut-over window per partner, dan menambah telemetri untuk memantau kegagalan dari sisi partner. Berhasil migrate 100+ partner tanpa incident besar.

Pernah debug issue production yang sulit?

Saat partner melaporkan transaksi gagal, alurnya: reproduce dengan payload mereka → cek log di Grafana sekitar timestamp → identifikasi apakah ini integration error (sisi partner: payload salah, credential expired, network) atau system error (sisi kami). Kalau integration, saya dokumentasikan perbaikannya dan walk-through ke partner; kalau system, saya raise ke system analyst dengan reproduction.

Kenapa backend?

Karir saya dimulai sebagai PHP programmer di AGIT yang banyak ke integration. Lalu pindah ke BAU Integration di LinkAja, bekerja langsung dengan system analyst untuk flow integrasi. Sisi backend / API itu menurut saya area dengan problem statement paling jelas: input jelas, output jelas, correctness bisa diukur.

Ready to test yourself?

Head over to the Quiz — 10 questions.