Interview: backend, databases, and design
The round where they ask how you would actually build and run the service you just described.
Topic 96 of 98 · 5 min to read · 50 min to build
After this topic you can
- Explain a Go service you built: its layers, storage and deployment.
- Explain how you would debug a slow endpoint or an OOM-killed pod, step by step.
- Explain how to stop one user reading another user's data.
What this round is testing
This is the round where they stop asking about language features and ask how you would build and run a real service. They are not checking whether you know a definition; they are checking whether you have made decisions and lived with them.
The pattern that scores well in every answer below is the same: say what you would do, then say what it costs, then say when you would change it. Someone who only knows the upside of a choice has not used it in anger.
"Walk me through a Go service you built"
- Use the project from this track. Structure the answer: what it does → how it is laid out → one decision you made and its cost → one thing you would change.
- The layout line: one package per domain,
handler → service → repository, dependencies pointing inward, wired by hand inrun() error, everything underinternal/. - The decision line: "no ORM —
database/sqlso I could see every query, at the cost of hand-writing scans. If it grew I would move tosqlc, not GORM." Naming the cost and the upgrade path is what they are listening for.
"Why no framework?"
- Since Go 1.22,
net/httproutes on method and path parameters. That was the main reason to add one. - A framework mostly wraps
func(http.ResponseWriter, *http.Request). Once you know that, any framework is quick to pick up. - Do not be rigid about it. "On a large team already using chi or echo, I would use theirs" is the right closing line.
"What is wrong with http.ListenAndServe in production?"
the answer
srv := &http.Server{ Addr: ":8080", Handler: handler, ReadHeaderTimeout: 5 * time.Second, // Slowloris ReadTimeout: 15 * time.Second, WriteTimeout: 30 * time.Second, IdleTimeout: 60 * time.Second,}"How do you handle authentication?"
- bcrypt for passwords. Identical error and similar timing for unknown-email and wrong-password.
- Short access JWT (15 min) plus a long refresh token that is stored as a hash and rotated on every use.
- Verify the signing method explicitly when parsing. Otherwise the token chooses its own algorithm, which is how
alg: noneand key-confusion bypasses happen. - Say why the access token is short: a JWT cannot be revoked, so the short window is what limits the damage. That trade-off is the actual question.
"How do you make sure one user cannot read another’s data?"
one line, and it is the whole answer
SELECT id, title, body FROM notes WHERE id = $1 AND user_id = $2"Your endpoint is slow. What do you do?"
- First, measure. pprof for CPU, and count database round trips. Do not start by guessing at Go code.
- The usual causes, most likely first: a query in a loop (N+1) → a missing index → a pool that is too small or unlimited → unbounded concurrency hammering a downstream → allocations in a hot loop → everything else.
- "The database is where the latency lives. One JOIN beats twenty round trips, and one index beats a month of Go micro-optimisation."
- Then:
-count=10andbenchstat, because a single benchmark run is noise.
"Your service is being OOM-killed in Kubernetes"
- Set `GOMEMLIMIT` to about 90% of the container limit. Without it the GC paces itself only by
GOGCand ignores the container limit, so the heap can grow until the OOM killer wins. - Check `GOMAXPROCS` against the CPU limit. Before Go 1.25 it defaulted to the *host’s* core count, so on a 64-core node with a 2-core quota you got 64 schedulers sharing 2 cores of quota, and CPU throttling showed up as latency spikes. From Go 1.25 the runtime reads the cgroup CPU limit on Linux, so say which version you run.
- Then look for the actual leak: goroutines that never exit (check the goroutine profile), small slices holding whole large buffers alive, and unbounded caches.
"How would you scale this to 10x traffic?"
- Measure first, then in this order: index the queries → cache the hot reads → add read replicas → shard. Say the order and why each is cheaper than the next.
- For a Go service specifically: the connection pool is your backpressure, so choose its size deliberately: 500 concurrent goroutines against a pool of 25 means 475 are queueing.
- Horizontal scaling implications you own: no in-process state, no local disk for uploads (move to S3), rate limiting moves to Redis or every instance allows the full limit.
"How do you deploy it?"
- Multi-stage Docker build,
CGO_ENABLED=0, distroless or scratch base, non-root user. About 15MB, with no shell and no package manager to attack. - Migrations run separately from the app, and must be backwards compatible with the currently-running code: add a nullable column, deploy code that writes it, backfill, then tighten. Never rename in one step.
/livezand/readyzas separate checks, because wiring a DB ping into liveness restarts every pod at once during a blip.
"How do you know it is working?"
- Structured logs with
log/slog, JSON in production, a request id threaded through the context so one failure is one grep. - Four numbers: request rate, error rate, latency percentiles (p50/p95/p99, never the mean), and saturation — pool usage, queue depth, goroutine count.
- Never log passwords, tokens, whole
Authorizationheaders, or full request bodies.
The short version
- Structure the project answer: what → layout → one decision and its cost → one thing you would change.
- Owner scoping belongs in the SQL. That single line answers the whole security question.
- Slow endpoint: measure, then N+1, then indexes, then the pool. Go code is last.
GOMEMLIMITandGOMAXPROCSare the two answers to "it misbehaves in a container" (the second is automatic from Go 1.25, but only whengo.moddeclaresgo 1.25or later).
Remember: Every design answer is stronger when you name what it costs you. "I chose X, it cost me Y, and here is when I would switch" is the sentence they are listening for.
Build this before moving on
Write a one-page description of your project: what it does, the folder layout, three decisions with their costs, and two things you would change. Then say it out loud in under three minutes.Then try these in your own editor
- 1Draw your service on paper — client, server, database, uploads — and mark where each failure mode lives.
- 2Pick three decisions you made and write down what each one cost. If a decision has no cost, you have not understood it.
- 3Explain N+1 and its two fixes without using the word "database".
- 4Time yourself explaining graceful shutdown, from SIGTERM to process exit, in 60 seconds.
Official documentation