Skip to content

Go Developer interview questions

100 real questions with model answers and explanations for Senior Go Developer candidates.

See a Go Developer resume example

Practice with flashcards

Spaced repetition · Hunter Pass

Questions

concurrencystructs

I would make one errgroup own the whole fan-out and cap it at the downstream limit of 60 calls.

  • I would create the group with errgroup.WithContext(requestCtx), call SetLimit(60), and launch each tenant call with g.Go using a per-iteration tenant value.
  • Every call would receive the group context, so the first returned error cancels siblings and no goroutine can outlive g.Wait.
  • If measurements show 120 ms call latency, 240 tenants at 60-way concurrency require four waves and about 480 ms before measured tail overhead; 120 ms must not be assumed without data.
  • This chooses fail-fast semantics; if partial tenant data were valid, I would collect per-tenant errors instead of returning them from g.Go.

Why interviewers ask this: The interviewer is checking whether the candidate can combine errgroup lifetime ownership, bounded parallelism, capacity math, and explicit failure semantics.

pricinghttpresilience

I would reserve 100 ms for response work and derive both child contexts from the caller's remaining deadline rather than giving each call 900 ms.

  • After about 40 ms of validation, I would use time.Until(parentDeadline) and cap profile at 300 ms and pricing at 500 ms, while both still inherit the roughly 760 ms shared downstream budget.
  • I would use context.WithTimeoutCause for each cap and context.WithCancelCause for an application decision such as invalidating both calls after a required profile result fails.
  • Each client call must accept that child context, and retries start only when the remaining budget covers backoff plus the measured p95 call time.
  • I would inspect context.Cause for metrics and logs, while mapping errors.Is(err, context.DeadlineExceeded) and context.Canceled to the transport contract.

Why interviewers ask this: A strong answer treats deadlines as a shrinking end-to-end budget and keeps timeout, caller cancellation, and application cancellation distinguishable.

dependenciesdata-structures

I would start with 100 workers because Little's Law gives about 96 concurrent calls and the dependency cap leaves only modest headroom above that.

  • I would run 100 fixed worker goroutines over a bounded jobs channel, with every call using the job context and a defer that releases any per-job resource.
  • A 200 ms queue budget at 1,200 jobs per second permits about 240 queued jobs; at 16 KiB per job that buffer retains roughly 3.75 MiB.
  • When the channel is full, admission would block only until ctx.Done or reject the job, rather than creating another goroutine and exceeding 110 in flight.
  • I would tune from queue latency, worker utilization, downstream p95, and rejection rate because an 80 ms mean can hide a tail that makes 100 workers insufficient.

Why interviewers ask this: The interviewer is evaluating whether pool size and queue capacity come from measured throughput, latency, dependency limits, and memory cost.

designlatency

I would read runtime.GOMAXPROCS(0) and begin with at most eight compression workers, then leave one or two processors free if the same process serves latency-sensitive RPCs.

  • Eight fully busy workers have a theoretical ceiling near 160 jobs per second at 50 ms each, while adding 80 runnable workers creates scheduling delay rather than more CPU.
  • I would use six workers for a mixed RPC process, a bounded input channel, and immediate admission failure once the queue would exceed the job deadline.
  • I would capture a CPU profile with runtime/pprof and a scheduler trace with runtime/trace to distinguish CPU saturation from allocation, GC, lock, and scheduling costs.
  • If sustained demand exceeds six-worker capacity, I would scale pods or isolate compression instead of raising GOMAXPROCS beyond the 8-CPU quota.

Why interviewers ask this: The question tests whether the candidate ties CPU parallelism to GOMAXPROCS and measured capacity rather than goroutine count.

concurrencydata-structuresbackpressure

I would cap the channel near 80 items because 80 divided by 400 items per second consumes the full 200 ms queue budget.

  • The 100-item-per-second deficit fills that buffer in about 0.8 seconds, so a larger channel would only delay overload and make expired work look accepted.
  • Producers would use a select between jobs <- item and ctx.Done, with an explicit overload response when the admission deadline expires.
  • Workers would dequeue in channel order, check the item's context, and skip processing when it has expired; a channel cannot remove an arbitrary expired item from the middle.
  • The real capacity fix is more consumers or less input; buffering smooths bursts but cannot turn 400 items per second into 500.

Why interviewers ask this: A strong answer connects channel capacity to queue-latency math and defines how overload propagates to producers.

estimationsharding

I would run at most eight shard calls concurrently and write each successful result into a preallocated 40-slot slice at its shard index.

  • Eight-way fan-out produces five waves; after reserving 250 ms of the 1-second deadline for merge and response work, the measured maximum call latency in each wave must sum to at most 750 ms.
  • A shard error would be stored beside that index rather than canceling healthy siblings, while the parent context deadline would still stop all unfinished calls.
  • A sync.WaitGroup or errgroup whose functions return nil would join every worker before one coordinator counts successes and emits results in index order.
  • I would return partial output only at 36 or more successes and include failed shard IDs; below that threshold the whole request fails.

Why interviewers ask this: The interviewer is checking bounded fan-out, race-free fan-in, ordered output, deadline handling, and a precise partial-success contract.

batchresiliencereact

I would let a blocking select wait on input, ctx.Done, and a timer, with no default case in the main loop.

  • A time.NewTicker at 200 ms drives normal flushes, while batch work must accept cancellation or have a measured upper bound below 50 ms so processing cannot hide ctx.Done past the reaction target.
  • On ctx.Done I would stop the ticker, stop accepting work, and run any required final flush with a separate short shutdown context capped by the remaining 50 ms budget.
  • I would use default only for a deliberate nonblocking try-send, such as dropping telemetry into a 100-item channel and incrementing a dropped counter when full.
  • Because select does not prioritize cancellation, I would check ctx.Err before starting bounded processing and make every blocking I/O call use its context.

Why interviewers ask this: A strong answer understands blocking select behavior, timer cleanup, the limited role of default, and cancellation fairness.

concurrencyresilience

I would give channel-close ownership to one coordinator after all six producers finish, never to an individual producer or the receiver.

  • A sync.WaitGroup starts at six, each producer defers Done, and a coordinator waits before calling close(records) exactly once.
  • Every producer send uses select with records <- record and ctx.Done so cancellation can release a producer blocked behind the consumer.
  • The consumer ranges until close during normal completion, but also stops expensive processing on ctx.Done and still participates in the agreed drain-or-cancel protocol.
  • A buffer may absorb a measured burst, but it does not change close ownership and cannot be relied on to prevent blocked sends.

Why interviewers ask this: The interviewer is evaluating whether the candidate can define a single close owner and make every blocking edge cancellation-safe with multiple producers.

concurrencymemory

I would use golang.org/x/sync/semaphore.Weighted with 1,536 MiB of permits, leaving about 512 MiB for the Go heap, stacks, and runtime overhead.

  • Each job calls Acquire(ctx, weight) with 64, 256, or 768 units and defers Release(weight), so two 768 MiB jobs or six 256 MiB jobs can run concurrently.
  • Admission respects the request deadline, and any job above the 1,536-unit ceiling is rejected before Acquire because it can never succeed.
  • I would derive weights from peak retained memory measured under load, not payload size, and alert when actual RSS approaches the 2 GiB cgroup limit.
  • A large waiter can delay smaller jobs, so if 64 MiB jobs have a tighter SLA I would use separate classes or reserved permits rather than pretending one weighted queue is fair.

Why interviewers ask this: The question tests whether the candidate can model heterogeneous resource cost while accounting for headroom, cancellation, and queue fairness.

concurrencydata-structuresownership

I would make the uploader own one dispatcher and four workers, expose Submit and Close, and separate a bounded Close call from eventual lifecycle joining.

  • NewUploader creates an internal cancellable context, starts all five goroutines in one sync.WaitGroup, and makes workers select on jobs and that internal context.
  • Submit(ctx, item) sends to the dispatcher and waits for acknowledgment; once shutdown starts, concurrent or later submissions receive ErrClosed.
  • Close(ctx) uses sync.Once to initiate stop and cancel the internal context, then selects between a done channel closed after Wait and ctx.Done; a deadline can make Close return before every goroutine exits.
  • The lifecycle owner must eventually join done and only then release shared clients or files, while worker operations must honor cancellation or have bounds so that join can finish.

Why interviewers ask this: A strong answer gives every goroutine, channel, shutdown transition, and resource one explicit owner across normal and timed-out closure.

concurrencyauthresilience

I would represent the slow operation as a reservation with an identity and make only short state transitions under the mutex.

  • Under the lock, check available capacity, create a unique pending reservation, count it toward reserved so reserved <= limit remains true, record the state version, then unlock before the 40 ms call.
  • After the call, reacquire the lock and finalize that same pending reservation on success or roll it back on a definitive failure; an ambiguous result remains pending for reconciliation, and both transitions must be idempotent because cancellation and retries can race with completion.
  • Context cancellation does not prove the remote operation failed. Use an idempotency key and reconcile an ambiguous result, otherwise a local rollback can disagree with a remote success.
  • A snapshot-and-version alternative can call first and commit only after rechecking the version and invariant, but contention may waste calls and a rejected commit may require compensation for a completed remote side effect. I would choose it only if capacity cannot be reserved provisionally.

Why interviewers ask this: The question tests a two-phase critical-section design that keeps a numeric invariant while handling stale state and ambiguous external side effects.

concurrency

I would choose from contention benchmarks because RWMutex helps only when concurrent read time repays its extra bookkeeping and writer coordination.

  • At 99:1, RWMutex may let many 80 ns reads overlap, but the benefit can remain small if lock overhead dominates the protected work.
  • At 70:30, pending and frequent writers reduce reader overlap, so a plain Mutex often has better throughput and more predictable tail wait.
  • Go blocks new readers behind a waiting writer, which prevents indefinite writer starvation but can create a convoy of readers around each write.
  • I would run both ratios with the real key distribution and report operations per second plus p50 and p99 acquisition time, not infer the result from the ratio alone.

Why interviewers ask this: A strong answer knows RWMutex semantics and requires measurements that include critical-section duration, contention, and tail latency.

snapshotconfigconcurrency

I would publish each immutable configuration as one atomic pointer, but I would not represent the used-at-most-limit invariant with unrelated atomic counters.

  • Build the full 2 KB value privately, then Store its pointer; a reader that Load returns that pointer observes the writes sequenced before the publication.
  • Never mutate a published snapshot, because atomic pointer publication does not make later field writes safe against 250,000 concurrent reads.
  • Separate atomic loads and updates of used and limit can expose or create a state where used exceeds limit even though every individual operation is atomic.
  • Protect the compound quota transition with a mutex, or encode the complete state in one CAS-able value and retry the whole transition after a failed CompareAndSwap.

Why interviewers ask this: The question separates safe publication of immutable state from the stronger atomicity required by a multi-value invariant.

aggregationstructs

Send each fully initialized pointer through a channel because a channel send is synchronized before completion of the corresponding receive.

  • A worker must write every result field before sending the pointer and must not mutate that object after ownership is handed off.
  • The aggregator may read those preceding fields after receiving the pointer without an additional mutex for that object.
  • Starting the aggregator goroutine or observing that enough time passed creates no visibility guarantee, and a shared slice index without synchronization is still a race.
  • For a close-based completion signal, closing the channel is synchronized before a receive that returns the zero value because the channel is closed.

Why interviewers ask this: The interviewer is checking precise Go memory-model reasoning about publication, ownership transfer, and operations that do not synchronize.

data-structuresconcurrency

I would keep the queue, count, and closed flag under one mutex and use separate notEmpty and notFull conditions for the two predicates.

  • Producers wait in a loop while count equals 1,024 and the queue is open, then recheck closed under the mutex before enqueueing; consumers wait while the queue is empty and open, and return when it is empty and closed.
  • Enqueue signals notEmpty, dequeue signals notFull, and shutdown sets closed under the mutex and broadcasts both conditions so all producer and consumer waiters can recheck their predicates.
  • The loop is required because another awakened goroutine can change the predicate before this waiter reacquires the lock, even though Go Cond does not wake without Signal or Broadcast.
  • A buffered channel already provides the 1,024-item bound, send and receive blocking, select, and close semantics; Cond is useful when admission depends on richer shared predicates or coordinated broadcast.

Why interviewers ask this: A strong answer gives the exact Cond predicate protocol and explains what channel semantics would remove from the custom design.

concurrency

I would wrap successful immutable initialization with OnceValue so all 200 callers share one completed invocation and receive the same result.

  • Concurrent callers block until the single function call returns, and later calls return the cached value without running initialization again.
  • If the function panics, every call to the returned function panics with the same value; OnceValue does not retry after a panic.
  • If initialization returns an error, OnceValues can cache the value and error pair, which also means a transient first error is cached rather than retried.
  • When retries are required, use an explicit mutex-protected state machine with backoff instead of hiding retry policy inside a Once function.

Why interviewers ask this: The interviewer is evaluating exact once-only, panic, and cached-error semantics rather than simple singleton familiarity.

concurrencyshardingcaching

I would begin with a typed map protected by a lock, then move only after contention profiles and workload benchmarks justify a specialized option.

  • Map plus Mutex or RWMutex gives clear compound operations, typed values, and snapshot logic, and is often sufficient when 30,000 writes are spread across keys.
  • sync.Map is optimized for entries written once and read many times or for goroutines operating on disjoint key sets; Range is not a consistent snapshot and multi-key invariants still need coordination.
  • Sharding by a stable hash can spread 96 goroutines across, for example, 64 locks, but resizing, global eviction, and exact size accounting become more complex.
  • I would replay the measured key skew and report throughput, p99 wait, allocations, and mutex profiles because a hot key can defeat both RWMutex and sharding.

Why interviewers ask this: The question tests whether the candidate matches concurrent map semantics to access patterns and validates complexity against measured contention.

concurrencythroughput

I would suspect cache-line ownership traffic because independent counters can still contend when writes target the same hardware cache line.

  • Compare adjacent and padded layouts with a parallel benchmark, CPU profiles, and hardware counters where available; separate allocations alone do not guarantee distinct cache lines.
  • Give each worker a private local counter and combine 96 totals after the loop, removing atomic operations and shared cache-line writes from the 20,000,000-iteration hot path.
  • If live reads are required, use padded sharded counters and verify the actual addresses, field offsets, and stride in the measured binary instead of assuming the allocator or a source-level layout provides isolation.
  • A 64-byte or 128-byte stride is architecture-specific and increases memory footprint, so benchmark and verify the layout for each deployment target.

Why interviewers ask this: A senior answer identifies coherence traffic, prefers local aggregation, and requires measured or address-verified isolation rather than assuming allocations or padding map to cache lines.

cachingconcurrency

I would create a seeded, repeatable stress test that overlaps Get, Set, Delete, and eviction, then run it repeatedly under the race detector.

  • Start all 40 goroutines from one barrier, derive each operation stream from recorded seeds over fixed hot and cold key sets, perform 100,000 total operations, and assert cache invariants after every group finishes.
  • Run go test -race -count=100 ./path/to/cache and vary GOMAXPROCS and recorded seeds in separate jobs to sample more schedules; a seed makes generated workloads replayable, not goroutine scheduling deterministic.
  • Keep a smaller -race workload if detector overhead makes 100 repeats impractical, but retain a non-race high-volume test for logical corruption and liveness.
  • A clean run means only that the detector reported no race on the observed executions; it does not prove linearizability, absence of deadlocks, race freedom on other schedules, or safety of unexecuted and uninstrumented code.

Why interviewers ask this: The interviewer is looking for a replayable concurrent workload and an accurate boundary around what observed clean race-detector runs can establish.

estimation

I would allocate one Timer per connection, reset it for the 100 ms deadline, and stop it when the connection loop exits.

  • time.After creates a new timer on every iteration, so 50,000 messages per second add avoidable allocations and timer-heap work even though modern Go can reclaim unreferenced timers.
  • On Go 1.23 and later, Reset and Stop provide an unbuffered timer-channel contract without stale values after they return; code supporting older Go must use the documented stop-and-drain reset pattern.
  • Keep timeout handling in the same select as message and cancellation handling, and ensure only one goroutine owns timer reset and receive operations.
  • For periodic work use NewTicker and defer Stop; Stop does not close ticker.C, so a receiver must also select on context cancellation rather than range until channel closure.

Why interviewers ask this: A strong answer combines hot-path allocation control with version-aware Timer semantics and explicit ticker shutdown ownership.

Locked questions

  • 21

    An 8-core Go service is CPU-bound for a representative 60-second test, and its CPU profile contains about 480 CPU-seconds of samples. How would you choose what to optimize from pprof?

    optimizationprofiling
  • 22

    A Go process shows 1.4 GiB in heap inuse_space but 96 GiB in alloc_space since startup. What do those two pprof views tell you, and which would you use first for memory reduction?

    concurrencydata-structuresmemory
  • 23

    For a 10-minute load test with 40,000 goroutines, how would you configure goroutine, block, and mutex profiles without leaving maximum-overhead sampling enabled?

    concurrencyconfigload-testing
  • 24

    A hot parseRecord function runs 2 million times per second and accounts for 18 MB/s of allocations. How would you use escape analysis to decide whether an API change is justified?

    memoryapi
  • 25

    A batch normally contains 10,000 records; a benchmark reports 4,230,000 B/op and 19 allocs/op when building a slice and map. How would you evaluate preallocation?

    decision-makingbatchslices-maps
  • 26

    A cache stores a 1 KiB subslice from each parsed 64 MiB payload, and 20 entries retain about 1.25 GiB. What would you change?

    caching
  • 27

    A sync.Pool normally serves 32 KiB buffers, but occasional 16 MiB responses make the process retain hundreds of megabytes between GCs. How would you redesign the pool policy?

    concurrencymemory
  • 28

    How would you set GOGC and GOMEMLIMIT for a Go service in a 2 GiB container when cgo allocations, external mappings, and thread stacks outside Go runtime accounting can consume 400 MiB at peak?

    gccontainersconcurrency
  • 29

    Under a stable load, gctrace shows about 12 collections per second with heap transitions near 600->1100->700 MB, while runtime metrics attribute 2.5 of 8 CPU cores to GC. How would you tune and validate the service?

    validationmonitoringdata-structures
  • 30

    Implementation B is 7% faster than A in one Go benchmark run. What benchmark design and sample set would you require before adopting B in a request path handling 50,000 RPS?

    decision-makingdesign
  • 31

    A Go parser converts 2 million 256-byte []byte records to string per minute, about 512 MB/min or 8.5 MB/s. Would you use unsafe for zero-copy conversion, and what lifetime and immutability contract would you require?

    immutability
  • 32

    A service wants to cast each 24-byte network header to a struct with unsafe.Pointer to save 40 ns at 3 million packets per second. How would you validate or reject it, and what can checkptr not prove?

    validationstructs
  • 33

    A gateway makes 5 million cgo calls per second to transform one 16-byte record, and C may retain batches after a call. How would you redesign the boundary while obeying cgo pointer rules?

    gatewaybatch
  • 34

    A Go image service uses C.malloc for 600 concurrent 12 MB workspaces, so about 7.2 GB sits outside the Go heap and is invisible to ordinary heap profiles. How would you own, measure, and release that memory?

    concurrencydata-structuresmemory
  • 35

    A service must scan a 20 GB file under a 6 GB container limit and is considering unix.Mmap instead of 64 parallel pread calls. How would you choose and safely manage mmap on Unix?

    containers
  • 36

    A client must send 10,000 protobuf messages of 1 KB within 2 seconds and may need intermediate acknowledgments and resume. Would you use unary RPCs, batching, a client stream, or a bidirectional stream?

    batchmicroservices
  • 37

    An external request has an 800 ms deadline and passes sequentially through four grpc-go services before returning a response. How would you allocate and propagate the budget so one slow hop cannot consume all 800 ms?

    estimationgrpcmicroservices
  • 38

    A grpc-go API receives 20,000 unary calls per second, 3% are unauthenticated, and the tenant limit is 500 calls per second. In what exact order would you chain recovery, tracing, authentication, and rate-limiting interceptors?

    grpcautherror-handling
  • 39

    A Kubernetes pod serves HTTP and grpc-go and consumes a broker, with terminationGracePeriodSeconds set to 30 and 2,000 messages in flight. What exact graceful-shutdown sequence would you implement?

    httpgrpckubernetes
  • 40

    A grpc-go service runs 4 replicas, needs startup warmup, serves 90-second streams, and must drain through a load balancer during rollout. How would you design health and Kubernetes readiness using the gRPC health service?

    designload-balancingmicroservices
  • 41

    A request crosses 4 Go layers before PostgreSQL returns ErrNoRows, and the HTTP boundary must still recognize the domain sentinel with errors.Is. How would you wrap the error without losing useful context?

    concurrencyerror-handlinghttp
  • 42

    A signup service validates 12 fields and must expose field-level failures to both HTTP and gRPC clients without importing either transport into the domain package. How would you use typed errors and errors.As?

    httpgrpcvalidation
  • 43

    Four independent validators run in parallel over a 50,000-row import; two may fail while valid rows should still be returned. How would you use errors.Join without making partial-result behavior ambiguous?

    joinsvalidation
  • 44

    A request has a 250 ms deadline, calls 3 downstream services, and returns through 2 internal layers. How do you preserve cancellation or deadline status while still adding Go error context?

    estimationresilienceconcurrency
  • 45

    A gRPC API serves 20 client teams and has 5 domain error categories, some retryable and some permanent. How would you make status mapping and retry semantics stable across releases?

    resiliencemicroservicesapi
  • 46

    Implement a stable-order generic deduplication helper for 10 million IDs, where callers pass either string IDs or defined integer ID types. What constraint and memory trade-offs would you choose?

    queriesgenericsmemory
  • 47

    A numeric helper adds offsets to 2 million counters, including a defined type shardCount whose underlying type is int. How would a ~int constraint preserve that type, and what limitations would you document?

    sharding
  • 48

    You need a reusable map-and-filter worker helper for 5 million records per minute. A benchmark shows generics at 38 ns/op with 0 allocations, an interface version at 41 ns/op with 0 allocations, and reflection at 190 ns/op with 2 allocations. Which design would you ship?

    genericstypesinterfaces
  • 49

    A service serializes 50 known message types at 200,000 messages per second; a generic implementation still needs reflection to inspect struct fields and consumes 22% of CPU. When would code generation be the better choice?

    genericsstructsserialization
  • 50

    A public Go module has 30 downstream modules using InferMap values without explicit type arguments. For module v2, you want to reorder its 2 type parameters and tighten one constraint. How would you assess compatibility and migration?

    hypothesis-testingmigrationsmodules
  • 51

    After a deploy, a Go service stays near 8,000 RPS but grows from 3,200 to 47,000 goroutines in 90 minutes; three pprof goroutine dumps taken 10 minutes apart contain 6,400, 9,100, and 11,800 copies of one stack in [chan send]. How would you triage it?

    deploymentprofilingconcurrency
  • 52

    A request launches 20 goroutines and returns after the first 12 results; at 120 RPS the process grows from 6,000 to 64,000 goroutines in one hour, and 57,000 stacks stop at resultCh <- result with [chan send]. What would you change?

    concurrency
  • 53

    An HTTP proxy handles 600 RPS and grows from 2,400 to 31,000 goroutines in 45 minutes; an upstream returns headers in 80 ms but stalls one response body in every 50 requests, and 14,000 stacks are blocked in io.ReadAll(resp.Body) with no client timeout. How would you contain and fix the leak?

    proxyresilienceconcurrency
  • 54

    A service has 2,000 tenant refresh loops, each using a 30-second ticker; tenants reconnect every 5 minutes on average, and after one hour goroutines rise from 2,100 to 26,000 with old loops waiting in [chan receive] at range ticker.C. What is the leak and the safe design?

    concurrencydesign
  • 55

    A Kubernetes pod receives SIGTERM with 18,000 goroutines, still has 6,700 after 25 seconds, and is killed at its 30-second grace limit; the final dump shows 5,900 broker workers in [select] and 700 goroutines under sync.WaitGroup.Wait. How would you repair the shutdown leak?

    concurrencykubernetes
  • 56

    You fixed a component whose Start creates 8 workers and 2 tickers, but its old Stop leaked workers whenever a consumer quit after 3 results; what regression test would you require across 100 Start and Stop cycles?

    componentsregression
  • 57

    A control pool climbs from 9,000 to 84,000 goroutines over 12 hours, while a patched canary at the same per-pod RPS stays between 9,100 and 10,400; dumps at hours 0, 2, 6, and 12 show the suspect [chan send] stack falling from 1,800 to 35 and then staying between 30 and 40, while 5,000 goroutines remain in [IO wait]. What would convince you to roll out?

    concurrencydeployment-strategies
  • 58

    At 18,000 RPS, a deploy raises the goroutine count from 900 to 31,000 in 4 minutes: the dispatcher is sending the next job to persistCh while the persister is sending the previous result to an unbuffered ackCh. How would you diagnose and fix this channel cycle?

    concurrencydeployment
  • 59

    After a release, a transfer service at 9,000 RPS jumps from 85 ms p99 latency to a 30-second timeout: the request path locks accountMu then ledgerMu, while reconciliation locks ledgerMu then accountMu. How would you handle the incident and prevent recurrence?

    incidentslatencyreact
  • 60

    A configuration service has 64 reader goroutines and refreshes every 500 ms; after a change, the refresher keeps RLock while calling Lock to update the snapshot, and read p99 rises from 12 ms to 20 seconds. What is happening and how would you redesign it?

    concurrencysnapshotconfig
  • 61

    A coordinator launches 10,000 import jobs, but 0.8% of batches return with 20 to 80 missing results and some hang until a 60-second watchdog; workers call WaitGroup.Add inside the new goroutine and one error path skips Done. How would you repair it?

    concurrencybatch
  • 62

    A Go API runs at 1,200 RPS with database/sql MaxOpenConns set to 80; when a downstream call inside each transaction slows from 200 ms to 4 seconds, 900 goroutines appear stuck and p99 reaches 15 seconds. How would you prove pool exhaustion rather than a deadlock and recover?

    sqldatabasetransactions
  • 63

    One deploy cuts throughput from 22,000 to 8,000 RPS and raises p99 from 140 ms to 2.8 seconds; goroutine stacks show both channel sends and Mutex.Lock waits. How would you use Go block and mutex profiles to identify the dominant liveness bottleneck?

    concurrencydeploymenthealth-checks
  • 64

    During a rollout, 4 of 12 Go pods stop making progress, 28% of requests hit a 5-second timeout, and the broker backlog grows by 30,000 messages per minute. What safe containment sequence would you use before the deadlock root cause is fixed?

    backloglockingresilience
  • 65

    At 30,000 RPS after a rollout, live heap rises from 750 MiB to 1.55 GiB in 20 minutes, RSS rises from 1.1 GiB to 2.3 GiB, an inuse_space diff attributes 720 MiB to cache insertion, and alloc_space shows 140 GiB in JSON decoding; what do you investigate first?

    cachingdata-structures
  • 66

    A cancellation storm leaves 14,000 goroutines blocked on one channel send, each stack retaining a decoded batch of about 192 KiB, and live heap grows from 820 MiB to 3.4 GiB after traffic recovers; how do you resolve the incident?

    concurrencydata-structureserror-handling
  • 67

    A custom retry ring drains from 100,000 items to 2,000, but live heap stays at 2.6 GiB instead of returning to 620 MiB; a heap profile shows 20 KiB payloads retained through slots before the ring head because dequeue advances the index without clearing the slot. How would you fix it?

    indexesresiliencedata-structures
  • 68

    A promotion fills an in-process map cache with 8 million keys; after expiry only 400,000 entries remain, but live heap stays 1.4 GiB above baseline and the heap profile points to map buckets. What would you do?

    concurrencydata-structurescaching
  • 69

    A Go service in a 4 GiB pod has a 1.2 GiB live heap, about 700 MiB of measured non-Go RSS, GOGC=200, no GOMEMLIMIT, and reaches 4 GiB during a 60-second burst; what initial tuning would you canary?

    deployment-strategiesdata-structuresgc
  • 70

    After a deploy, allocation rate rises from 1.1 GiB/s to 2.8 GiB/s, GC CPU from 9% to 31%, GC pause p99 from 0.7 ms to 4.5 ms, request p99 from 85 ms to 170 ms, while live heap stays near 900 MiB; how do you diagnose and mitigate it?

    deploymentdata-structures
  • 71

    An import pod has a 6 GiB cgroup limit and a 2.2 GiB idle RSS; each job peaks at 32 MiB of native memory plus 24 MiB of Go memory, 120 jobs run concurrently, and memory.current reaches 5.7 GiB in 90 seconds; how do you contain OOM without corrupting imports?

    memoryconcurrency
  • 72

    At 18,000 RPS, a Go checkout service's p99 rose from 85 ms to 310 ms after enabling new request validation, CPU climbed from 4.2 to 7.8 of 8 cores, and a CPU pprof attributes 34% of samples to regexp.Compile; what would you do?

    validationregexprofiling
  • 73

    At 11,000 RPS, an authorization service's p99 increased from 65 ms to 510 ms while CPU stayed at 52% and goroutines grew from 4,000 to 38,000; a goroutine profile shows 29,000 waiting on one Mutex, and mutex and block profiles point to a cache lock held across a 35 ms Redis call. How would you resolve the incident?

    concurrencyredisauth
  • 74

    Across 10 pods at 14,000 RPS, p99 rose from 95 ms to 370 ms and allocation rate doubled from 1.2 to 2.4 GB/s, so the team suspects GC; GC pauses remain below 0.8 ms with 9% GC CPU, while a runtime trace shows 230 ms of worker-queue wait as downstream mean latency grows from 55 ms to 145 ms and its limit is 120 in-flight calls per pod. What decision would you make?

    latencydata-structures
  • 75

    At 2,400 RPS, a release expanded a search request from 6 to 18 parallel dependency calls and p99 moved from 210 ms to 980 ms; each dependency call has p50 32 ms, p99 620 ms, and a 1% chance of exceeding 500 ms. How would you stop the fan-out incident and redesign the path?

    incidentsfan-outdependencies
  • 76

    At 12,000 RPS across 8 Go API pods, p99 rose from 75 ms to 640 ms although PostgreSQL query p99 is 16 ms; each sql.DB has MaxOpenConns 40, InUse stays at 40, pool wait contributes 510 ms, and a new audit path holds 5% of transactions for 180 ms during a remote call. The database permits 600 application connections. What would you change?

    sqldatabasetransactions
  • 77

    At 20,000 RPS across 20 eight-core pods, p99 for ordinary API calls rose from 80 ms to 290 ms after synchronous PDF export launched; export is only 4% of requests, but endpoint-labeled CPU pprof data assigns it 55% of CPU and each export consumes 120 ms of CPU. How would you contain this noisy endpoint?

    endpointsprofiling
  • 78

    During a 10% canary at 16,000 total RPS, the old Go version holds p99 at 92 ms and errors at 0.2%, while the canary receives 1,600 RPS with p99 480 ms, errors 1.7%, and 30% higher CPU for 6 minutes; its CPU profile attributes 41% to synchronous success-log encoding. Do you roll back, and what happens next?

    deployment-strategiesrollback
  • 79

    At 70,000 requests per second, three of 24 Go pods exit with fatal error: concurrent map writes while updating a 2 million-entry routing table; how would you capture evidence, reproduce the race, and fix it?

    concurrency
  • 80

    One response in 50,000 has a corrupted JSON suffix after a writer goroutine queues a 32 KiB buffer and returns it to sync.Pool before the socket write completes; how would you prove and fix the reuse race?

    concurrencydata-structuresmemory
  • 81

    Eight goroutines parse 25,000 rows each into one shared slice, but production batches occasionally contain 197,000 instead of 200,000 results; how would you catch and repair the slice race?

    concurrencyslices-mapsbatch
  • 82

    About one price response in 2 million contains an amount from request A and a currency from request B; a timeout path returns while a fallback goroutine is still writing both fields of a shared result struct. How would you catch and fix the race?

    concurrencystructsresilience
  • 83

    A race appears only near 80,000 requests per second, while your measured race-enabled binary uses 3.8 times the CPU and 7.2 times the memory; how would you use race-detector staging and a canary without destabilizing production?

    deployment-strategiesmemory
  • 84

    One of 12 pods corrupts a 4 KiB mutable cache entry about once every 6 hours, and ordinary load tests do not reproduce it; how would you turn logs, dumps, and a suspected reader-writer interleaving into a deterministic regression test and verified fix?

    load-testingregressioncaching
  • 85

    Twelve minutes after a deploy, 18 of 1,200 checkout requests panic on cfg.Retry.Policy.MaxAttempts; how would you handle this nil-pointer incident and prevent a repeat?

    incidentsdeploymentresilience
  • 86

    An HTTP API serving 40,000 requests per second reports 25 handler panics per minute, and 10 occur after response headers are written; how would you design its recovery middleware?

    designmiddlewarehttp
  • 87

    A grpc-go server handles 12,000 unary calls per second and 4,000 active streams; one release causes 9 panics in unary handlers and 3 in stream handlers, so what recovery boundaries would you install?

    error-handlinggrpcmicroservices
  • 88

    A consumer runs 64 Go worker goroutines for 300,000 jobs per day, and one malformed payload has panicked 7 times and restarted the whole pod; where would you put recovery and what would happen to that job?

    concurrencyerror-handling
  • 89

    A 3-replica Go ledger service panics after updating the first of 2 in-memory indexes during an 800-account batch, and a checksum later finds 27 mismatches; should recovery keep that replica serving or crash it?

    indexesreplicationerror-handling
  • 90

    After clients disconnect, a Go API still shows 2,000 enrichment goroutines per minute running for up to 30 seconds because the handler calls context.Background; how would you fix the incident?

    concurrencyapiincidents
  • 91

    A poller creates context.WithTimeout(parent, 3*time.Minute) for 25,000 calls per minute but never calls cancel; calls usually finish in 20 ms, and a heap profile attributes about 80,000 live timer and context objects to that line. What would you change?

    data-structuresconcurrency
  • 92

    An ingress times out checkout requests after 1.2 seconds, the Go server allows 5 seconds, PostgreSQL allows 4 seconds, and clients retry at 1.2 seconds; traces show 31% of timed-out work continues for more than 3 seconds. How would you align the timeouts?

    resiliencepostgreskubernetes
  • 93

    A dependency returns a timeout at 480 ms on a request with a 500 ms deadline, yet the Go client performs two retries with 100 ms backoff and triples load during an outage; how would you stop doomed retries?

    resiliencedependenciesestimation
  • 94

    An HTTP handler returns 202 in 80 ms and starts invoice generation in a goroutine, but 4% of invoices disappear when the request context is canceled; how would you make the work durable?

    concurrencyhttp
  • 95

    HTTP requests time out after 800 ms, but PostgreSQL queries launched with db.Query keep running for 45 seconds and exhaust a 100-connection pool; how would you contain the incident?

    queriespostgrespooling
  • 96

    A junior engineer's retry loop leaked 18,000 goroutines in 15 minutes because channel sends ignored request cancellation; how would you mentor them while shipping a fix within 24 hours?

    concurrencyresiliencementoring
  • 97

    A concurrency PR due tomorrow must process 50,000 jobs per minute, but it starts one goroutine per job, closes the result channel from the receiver, and has no cancellation tests; how would you review and coach the author?

    concurrencytestingresilience
  • 98

    A Go engineer missed context cancellation and channel ownership problems in 4 of their last 6 reviews; what six-week learning plan would you create, and how would you measure its outcome?

    concurrencyownershipresilience
  • 99

    At 14:05, a Go deploy triggered send-on-closed-channel panics across 12 pods, causing a 38% error rate for 18 minutes; the author is a junior and seven engineers join the incident, so how would you facilitate it without blame?

    concurrencyerror-handlingjoins
  • 100

    Two Go engineers disagree on using a Mutex or an owner-goroutine channel for a state table handling 200,000 operations per second; how would you mentor the disagreement and settle it with a benchmark within 48 hours?

    concurrencyconflictmentoring