Question bank
115 questionsExplore foundational and challenging questions across Java/JVM, Python, SQL engines, Unix tooling, networking, and production operations.
Search questionsHTTP
Subject guidesWhat does idempotence guarantee for an HTTP operation?Idempotence describes the intended effect, not identical response bytes or status codes. POST needs an explicit deduplication contract before ambiguous retries are safe.
Idempotence describes the intended effect, not identical response bytes or status codes. POST needs an explicit deduplication contract before ambiguous retries are safe.
What should a client do with a valid 304 response to If-None-Match?A 304 validates a previously cached representation and does not provide a replacement body. Cache policy and authorization still control whether reuse is appropriate.
A 304 validates a previously cached representation and does not provide a replacement body. Cache policy and authorization still control whether reuse is appropriate.
Why does a byte offset alone not make a download safe to resume?The representation may have changed since the saved prefix was downloaded.
Use a validator such as a strong ETag with If-Range, validate the 206 Content-Range before append, and verify final integrity separately. An ETag is not necessarily a cryptographic digest.
Does If-Match make a lost-response write safely identifiable on retry?No; it identifies an expected version, not a logical operation.
A committed first attempt advances the validator, so a repeat with the old validator may fail with 412. Use a separate scoped idempotency contract when retries must recover the original result.
Security
Subject guidesWhy rotate a session identifier after authentication?Rotation limits session fixation. A session identifies a principal, while each protected operation still requires independent authorization.
Rotation limits session fixation. A session identifies a principal, while each protected operation still requires independent authorization.
A logged-in customer requests another customer’s invoice ID. What must the server do?Authentication alone does not authorize every object. Scope resource access to verified identity and tenant, not client-supplied identity fields.
Authentication alone does not authorize every object. Scope resource access to verified identity and tenant, not client-supplied identity fields.
Why does CORS not replace CSRF protection?A browser can send some authenticated cross-site requests even when the attacker cannot read the response.
CORS governs response readability for scripts; CSRF defenses prevent unwanted state changes using ambient credentials. Validate tokens and trusted origins independently for state-changing routes.
Why is a unique resource ID insufficient for tenant authorization?Identity selects a resource; trusted scope and action policy grant access.
Derive tenant context from verified membership, apply it in lookup and mutation predicates, and check the requested action. Cache hits, downloads, and background jobs need the same scope enforcement.
TypeScript
Subject guidesWhat does casting JSON with as Order do at runtime?Type assertions are erased. Treat untrusted data as unknown and validate its shape and domain constraints before relying on it.
Type assertions are erased. Treat untrusted data as unknown and validate its shape and domain constraints before relying on it.
Does Promise.all limit how many operations an eager map starts?Promise.all aggregates promises already supplied to it. Eagerly mapping a large list can start all work at once, so downstream capacity needs a separate concurrency bound.
Promise.all aggregates promises already supplied to it. Eagerly mapping a large list can start all work at once, so downstream capacity needs a separate concurrency bound.
Does AsyncIterable guarantee bounded buffering?No; an adapter can hide an unbounded push queue behind a pull-shaped interface.
A consumer can request one item at a time, but callback-backed sources still need an explicit capacity and overflow policy. Tie early iterator exit and cancellation to resource cleanup.
Why model missing, invalid, and unavailable as separate TypeScript results?They require different caller behavior and must not collapse into null.
Validate unknown runtime data, then preserve outcome meaning in a discriminated union. Exhaustive handling exposes new states during compilation; structural validation does not establish permissions or retry safety.
Kubernetes
Subject guidesWhat does a successful kubectl apply prove?API acceptance is not convergence. Inspect rollout status, Pod conditions, and events to determine whether the desired workload is actually ready.
API acceptance is not convergence. Inspect rollout status, Pod conditions, and events to determine whether the desired workload is actually ready.
Does updating a ConfigMap change environment variables in an already running container?Environment-based configuration generally needs replacement containers. Mounted configuration has different update behavior and the application must still reload it.
Environment-based configuration generally needs replacement containers. Mounted configuration has different update behavior and the application must still reload it.
Why can a Kubernetes object remain after deletion was requested?A controller has not removed its finalizer after completing external cleanup.
The API server records deletion and retains the object while finalizers remain. The owning controller must retry idempotent cleanup and remove only its own finalizer after confirmed completion.
Why can a Kubernetes drain be blocked by a healthy-looking deployment?Eviction permission depends on the budget and observed ready capacity.
A PDB can reject supported voluntary eviction when too few healthy selected pods would remain. It does not prevent node failures, guarantee replacement capacity, or govern every controller deletion.
What is the difference between readiness and liveness in Kubernetes?Readiness decides whether traffic reaches a pod, while liveness decides whether the container needs a restart.
Readiness is a traffic signal: if it fails, the pod is removed from service endpoints and users are not routed to it. Liveness is a health check for the process itself: if it fails, Kubernetes restarts the container. A pod can be alive but not ready, and that is often the correct state during startup or dependency warm-up.
What happens when a Kubernetes container reaches its CPU or memory limit?CPU can be throttled; exceeding a memory limit can trigger an OOM kill.
CPU usage above a configured limit is throttled, which can increase latency without stopping the process. Memory is not throttled in the same way: crossing the container limit can cause the kernel to kill the process, often reported as OOMKilled. Requests affect scheduling and utilization-based HPA calculations, so tune all values from observed workload behavior.
Why can a pod be CPU-throttled while its node is only 40% busy?CPU quota is enforced per container, so node-wide unused capacity may not be available beyond its limit.
A container can exhaust its CFS quota during a period even if other node CPUs are idle. Inspect container throttling counters and request/limit values alongside latency. Decide whether the limit is needed, whether requests/HPA targets match demand, or whether CPU work should be reduced; do not infer container headroom from node averages.
Which settings commonly cause 502s during a Kubernetes rolling update?Readiness, termination grace, endpoint withdrawal, and ingress draining may be misaligned.
Check whether readiness turns true before the app can serve, whether shutdown stops accepting work too early, and whether terminationGracePeriodSeconds/preStop allow endpoint withdrawal and connection draining. Also inspect maxUnavailable/maxSurge and ingress upstream errors. Correlate events, endpoint changes, and 502 timestamps before tuning a single probe.
DevOps
Subject guidesWhy promote the same immutable artifact rather than rebuild for production?A rebuild is a new artifact, even at the same source commit. Promotion preserves the tested output while environment configuration remains deliberate and observable.
A rebuild is a new artifact, even at the same source commit. Promotion preserves the tested output while environment configuration remains deliberate and observable.
Why can a binary rollback fail after a database migration?Rollback restores code, not every side effect. Expand-and-contract changes preserve compatibility during overlap, and recovery assumptions must be exercised.
Rollback restores code, not every side effect. Expand-and-contract changes preserve compatibility during overlap, and recovery assumptions must be exercised.
What makes a CI OIDC trust policy meaningfully narrow?It checks issuer, audience, repository and the intended protected job identity.
A valid signed token is not sufficient by itself. Match the intended claims, issue a narrowly scoped short-lived role, and prevent untrusted workflow code from running in that credentialed context.
What identity should a delayed scheduled-job retry preserve?Preserve the logical job and intended window, not the retry start time.
A logical run names the business partition; attempt IDs name executions of that run. Commit completion with the effect when they share storage, and handle remote effects with an explicit duplicate or reconciliation protocol.
Why do multi-stage Docker builds matter so much?They reduce the runtime image to just the files required to execute the service.
Multi-stage a build lets you compile in one environment and then copy only the final artifact into a slim runtime image. This reduces image size, shortens deployment time, lessens the attack surface, and makes it easier to reason about what the service actually needs to run. It is a packaging discipline, not just a size optimization.
Why build an artifact once and promote it through environments?The exact tested artifact should be the artifact deployed to production.
Rebuilding separately for staging and production can produce different binaries from the same apparent release. Build once, identify the artifact with its source revision and provenance, then promote that immutable artifact. Caches can accelerate builds, but a cache miss must not change correctness.
Why can COPY . invalidate dependency layers in a Docker build?Every later layer is invalidated when an earlier instruction input changes.
If the whole source tree is copied before dependency installation, any source edit changes that COPY layer and invalidates all subsequent build steps. Copy lockfiles first, install from them, then copy source. Confirm the result with build output and a clean build; cache reuse should improve speed, not alter correctness.
How do you safely recover a Terraform state lock after a crashed job?Verify the lock holder is truly gone and preserve state before force-unlocking.
Inspect lock metadata, backend state, and the pipeline that acquired it; confirm no apply is still running. Preserve a state backup and compare cloud reality before force-unlocking the specific stale lock. Then run and review a plan. Force-unlocking a live writer can permit competing state updates and corrupt tracking.
Java
Subject guidesWhat usually keeps an undeployed Java class loader alive?A live root still reaches an object, class, or thread state owned by the old loader.
Look for parent-owned registries, executor queues, thread locals, context class loaders, and callbacks. An unreachable cycle can be collected; a path from a long-lived root cannot.
Why share one Java deadline across several dependency calls?Fresh timeouts at each stage multiply the total wait.
Measure elapsed time locally with nanoTime and give each stage only the shared budget remaining. Expiry stops admission of more work; it does not prove a remote write was cancelled.
How is HashMap built internally?HashMap stores entries in buckets, resolves collisions with linked lists or trees, and resizes when load crosses a threshold.
HashMap uses an array of buckets and computes an index from the hash of the key. Each bucket may hold one or more entries. When collisions happen, Java stores entries in a linked list and later in a tree when the bucket grows large enough. The table resizes when the load factor is exceeded so the map keeps operations efficient. The key idea is balancing fast lookup with controlled memory use.
What is ConcurrentHashMap and why is it different from HashMap?ConcurrentHashMap is designed for concurrent reads and writes without locking the entire map.
Modern Java ConcurrentHashMap does not use the fixed lock segments from older implementations. It uses non-blocking reads and coordinates updates with CAS and synchronization at individual bins when needed. This allows unrelated keys to make progress concurrently. It protects map operations, not a multi-key transaction or mutable values stored inside it.
What is the difference between volatile and synchronized?Volatile provides visibility; synchronized provides both visibility and mutual exclusion.
A volatile field guarantees that a write is visible to other threads, but it does not make a compound operation atomic. synchronized locks a monitor and protects a block of code so only one thread executes it at a time. In practice, use volatile for state flags and synchronized for critical sections that need atomicity and ordering guarantees.
What happens when two Java HashMap keys have the same hash code?The keys share a bucket, then equality distinguishes entries within that bucket.
A hash helps select a bucket but does not establish key identity. HashMap checks equality among entries in the bucket; collisions can be stored in a list and, in sufficiently large bins, treeified under implementation conditions. Correct equals/hashCode behavior is essential, and resizing changes bucket placement without making hashes unique.
How does modern ConcurrentHashMap coordinate concurrent updates?It combines volatile reads, CAS operations, and synchronization scoped to bins when needed.
Modern Java implementations do not use the old fixed segment array commonly described in older explanations. Reads are generally non-blocking; initialization and some updates use CAS, while contended updates coordinate at a bin. Map operations are thread-safe, but multi-key invariants and mutable values still need their own synchronization design.
When should you use volatile, synchronized, or AtomicInteger?Choose based on whether you need visibility, mutual exclusion, or atomic operations on one value.
Volatile gives visibility and ordering for a field but does not make compound read-modify-write operations atomic. Synchronized protects a critical section and its invariants using a monitor. AtomicInteger provides atomic operations such as increment-and-get for one integer; it does not make a group of fields update transactionally.
What does it mean when a Java object becomes eligible for garbage collection?It is no longer strongly reachable from GC roots, though collection timing is not guaranteed.
An object becomes eligible when no strong-reference path leads to it from roots such as live thread stacks, static fields, or JNI references. Eligibility does not guarantee immediate collection or finalization. To diagnose retention, inspect heap dumps and dominator paths; do not rely on System.gc() as a fix.
How do OutOfMemoryError and StackOverflowError differ?Heap or native-resource exhaustion differs from exhausting one thread call stack.
OutOfMemoryError identifies an allocation resource that could not be satisfied, such as Java heap, metaspace, direct buffers, or native threads. StackOverflowError usually indicates an excessively deep call chain or runaway recursion in one thread. Read the exact message, capture JVM and container metrics, and use a heap dump or thread stack evidence before changing memory flags.
How does the JVM class-loading lifecycle work?Loading, linking, and initialization are distinct phases managed by class loaders.
A class loader locates and defines bytecode; linking verifies it, prepares class storage, and resolves symbolic references as needed; initialization runs static initialization in the specified order. Parent delegation is common but custom loaders can change identity: classes with the same name loaded by different loaders are distinct runtime types. Class-loader leaks often arise when long-lived references retain an application loader after redeployment.
How do String, StringBuilder, and StringBuffer differ?String is immutable; builders are mutable, and StringBuffer synchronizes its methods.
String values are immutable and can be safely shared. StringBuilder supports mutable append operations without synchronization and is usually appropriate for thread-confined construction. StringBuffer synchronizes individual methods, but that does not automatically make a multi-call workflow atomic; synchronization often costs more than needed when a builder is local to one thread.
What can ThreadLocal break when used with a thread pool?Pooled threads outlive requests, so forgotten thread-local values can leak data and memory across tasks.
Thread pools reuse worker threads. A ThreadLocal value can remain attached after a request ends, retaining large objects or exposing one request’s context to a later task if it is not overwritten. Clear it in a finally block or use a scoped context mechanism with well-defined propagation and cleanup.
How does CompletableFuture composition work, and what causes stalls?Completion stages form a dependency graph; blocking the wrong executor can starve that graph.
CompletableFuture represents a value that may complete later, with dependent stages triggered on completion. Async methods without an explicit executor commonly use a shared pool; blocking calls there can starve unrelated work. Prefer non-blocking composition, choose an executor suited to the task, set timeouts, and observe exceptional completion rather than calling join() throughout request paths.
What is ForkJoinPool work-stealing, and when is it a poor fit?Workers steal queued tasks to balance fine-grained CPU work, but blocking tasks can starve workers.
ForkJoinPool uses worker-local deques and lets idle workers steal tasks from others, which helps recursive, CPU-bound workloads with many small tasks. Long blocking I/O can occupy workers and reduce progress. Use a suitable dedicated executor or managed blocking strategy for blocking operations, and avoid creating huge numbers of tiny tasks with excessive scheduling overhead.
How do you detect and fix a Java deadlock?Find a cycle in lock ownership and waiting, then remove inconsistent nested lock ordering.
Capture repeated thread dumps with jcmd or jstack while the incident is active. A deadlock cycle shows threads waiting for locks held by each other; distinguish it from starvation or a slow dependency by checking whether owners can progress. Fix consistent lock order, shorten critical sections, or redesign ownership so both locks are not required together.
What happens when a Java service creates too many threads?Native stack memory, scheduling overhead, context switching, and file descriptors can be exhausted.
Each platform thread consumes native resources, including stack reservation, and excessive runnable threads add scheduling and context-switching overhead. The service may hit native-thread creation errors or degrade before that point. Bound executors, measure queue depth and task latency, and apply backpressure rather than creating one thread per unbounded unit of work.
When are WeakReference, SoftReference, and PhantomReference useful?They express different reachability and cleanup relationships, but are not general-purpose cache policies.
Weak references do not keep an object alive and are useful in structures such as canonicalizing maps when carefully designed. Soft references may be cleared under memory pressure, but their timing is not a predictable cache eviction policy. Phantom references support post-mortem cleanup coordination through a reference queue; they do not let code retrieve the referent.
What is false sharing in Java, and how can it hurt throughput?Independent hot fields on one cache line can cause cores to invalidate each other’s cache copies.
False sharing occurs when separate variables frequently written by different cores share a hardware cache line. The values are logically independent, but cache-coherence traffic makes updates contend. Confirm with profiling and workload measurements before padding or using specialized structures; layout optimizations are hardware- and JVM-sensitive.
How do you investigate high garbage-collection pauses in production?Correlate GC logs, allocation rate, live-set size, pause phases, and user latency before tuning.
Enable and inspect unified GC logs for pause duration, cause, heap before/after, promotion, and allocation behavior. Correlate with request latency and container memory. A large live set, allocation bursts, humongous objects, or memory pressure can imply different fixes; tune collector flags only after identifying which resource or workload pattern drives the pauses.
What happens when a Java thread calls wait()?It must own the monitor, releases that monitor, and waits until notified or interrupted.
Object.wait() requires ownership of that object’s monitor. The thread releases that monitor and enters a waiting state until notification, interruption, timeout, or spurious wakeup; it must reacquire the monitor before returning. Always wait in a while loop that rechecks the condition, and use higher-level concurrency utilities where possible.
How do you troubleshoot high thread contention in Java?Use repeated thread dumps and lock profiling to locate hot locks, then reduce serialization safely.
Capture repeated thread dumps and identify many threads blocked on the same owner or monitor. Use a profiler or JFR lock events to quantify contention and critical-section time. Reduce lock scope, shard independent state, batch updates, or use concurrent primitives only when they preserve the invariant; verify throughput and correctness under representative load.
How can a Java thread pool deadlock while threads are still alive?Workers can all block waiting for child tasks queued to the same exhausted executor.
If every worker submits a task to the same bounded executor and synchronously waits for that task, no worker remains to run queued children. This is thread-pool starvation, not necessarily a monitor deadlock. Avoid blocking composition on the same pool, separate workloads, or use asynchronous completion and bounded concurrency.
What evidence distinguishes high allocation from a Java memory leak?Compare post-GC live-set size and object retention paths over time.
High allocation can cause frequent collections while post-GC occupancy remains broadly stable. A leak tends to retain objects that should have become unreachable, so compare heap dumps and dominator paths across time. Check allocation rate, live set, GC logs, and process/container memory together before changing heap settings.
Why can a HashMap fail to find a key that was inserted?Mutable key fields or inconsistent equals/hashCode behavior can make lookup search a different bucket.
HashMap uses hashCode to choose a bucket and equals to identify a key within it. Equal values must share a hash, and hash-relevant state must not change while the object is used as a key. Check equality in both directions, inspect hash values, and prefer immutable key objects.
How do you debug a Java exception wrapped by a framework?Follow the complete cause chain to the deepest relevant failure and retain contextual stack traces.
Read the top exception and every Caused by section. Framework and future wrappers often report where failure surfaced, not its origin. Preserve stack trace, request identifier, runtime version, and safe configuration context. When translating an exception, chain the original cause rather than logging only its message.
Why does Spring throw BeanCurrentlyInCreationException for a circular dependency?The container cannot construct a dependency cycle safely, especially when both beans require constructor injection.
Bean A needs B while B needs A, so neither constructor can complete first. Treat the exception as an ownership/design signal: extract the shared responsibility, invert a dependency, or communicate through an event. Lazy lookup can defer resolution but does not remove the cycle or its coupling.
Why is blocking JDBC dangerous inside a Spring WebFlux event loop?A blocking call occupies a small Netty event-loop pool and stalls unrelated connections.
Reactive event loops depend on handlers returning promptly. Blocking JDBC parks the event-loop thread while it waits for the database, so many unrelated requests queue behind a few occupied threads. Use a reactive driver end-to-end or isolate unavoidable JDBC work on a bounded worker scheduler and constrain concurrency.
Python
Subject guidesWhat does an asyncio TaskGroup do after a child fails?It cancels unfinished siblings, waits for cleanup, and surfaces failures as a group.
Child cancellation is cooperative, so cleanup must run and cancellation should normally be re-raised. A task group scopes lifetimes; it does not roll back remote effects or make partial success a business policy.
What does asyncio queue completion actually prove?Every accepted item has been acknowledged, not necessarily committed successfully.
A bounded queue limits waiting items; workers hold additional active items. task_done releases unfinished-item accounting, while business success and durable retries require separate records.
When should I use async Python instead of threads?Async is best for I/O-bound work, while threads and workers are better for CPU-bound tasks or blocking libraries.
Use async when the code is mostly waiting on IO such as database calls, HTTP requests, or message queues. Use threads or process pools for CPU-intensive work or code that cannot cooperate with the event loop. The key is matching the concurrency model to the bottleneck, not adding async everywhere because it seems modern.
How do you prevent an async API from overwhelming dependencies?Bound concurrency and queue depth at the scarce resource, and enforce an end-to-end deadline.
Use bounded connection pools, semaphores or worker queues, request deadlines, and deliberate overload responses. Local limits must account for replica count because each replica has its own pool. Avoid unbounded in-memory tasks and retries that amplify load during an incident.
When should you choose a Python list, tuple, or set?Base the choice on ordering, mutation, duplicates, and membership operations.
A list is ordered, mutable, and permits duplicates. A tuple is an immutable sequence suited to fixed records, though named structures can improve readability. A set stores unique hashable values and is useful for membership; do not use it when output order or duplicates are part of the contract.
When is map or reduce clearer than a Python comprehension or loop?Use the form that makes transformation, laziness, and accumulator state easiest to understand.
map is lazy and can be concise with an existing named function; a comprehension often reads better when transformation and filtering are simple. reduce is appropriate for a well-defined associative fold, but sum, any, all, or an explicit loop often communicates intent better. Avoid hidden side effects because they make ordering and debugging difficult.
Why is a mutable default argument dangerous in Python?Default expressions are evaluated once, so the same mutable object is reused across calls.
A default list or dictionary is created when the function is defined, not every time it is called. Mutations therefore leak between calls. Use None as a sentinel and construct a fresh object inside, or use default_factory for dataclasses and similar models.
How do you find the root cause in a long Python traceback?Start with the exception and failing operation, then trace the first bad value to its producer.
Read the final exception type/message, locate the failing operation, and inspect the nearest application frame that supplied its input. Reproduce the smallest failing case and trace where that value was created or transformed. Add validation at uncertain boundaries and a regression test; do not catch and suppress the exception at the bottom of the stack.
How do you fix a Python TypeError caused by None?Trace why a value is absent and validate or model optionality where it enters the system.
Find the first operation that received None and trace the producer branch, database field, or external payload that supplied it. Decide whether absence is valid: represent it as Optional and handle it explicitly, or reject malformed input at the boundary. Blindly substituting an empty string or zero can hide an invalid state and change business meaning.
How can tracemalloc help diagnose Python memory growth?Compare traced allocation snapshots to identify Python allocation sites, then verify process-level memory too.
Start tracemalloc before the workload, take snapshots at comparable points, and compare line-level allocation differences. It tracks Python-managed allocations, not every native allocation from extensions or system libraries. Correlate it with RSS and object-retention behavior; growing allocation totals do not alone prove a leak if objects are later freed.
Why can a Python list not be an element of a set?Set members must be hashable, and a mutable list does not have a stable hash.
Sets and dictionary keys rely on a stable hash and equality relationship while a value is stored. A list is mutable, so changing it could invalidate the collection’s lookup structure; Python therefore makes lists unhashable. Use a tuple if its members are also hashable and the value should be immutable.
Is Python map eager or lazy?In Python 3, map returns an iterator that computes values as it is consumed.
Python 3 map is lazy: it returns an iterator and evaluates each mapped value as the iterator advances. Convert it to a list only when you need materialized results or repeated traversal. Lazy evaluation saves memory but exceptions may occur later when a consumer iterates.
What property should a reduce operation have for safe parallel combination?Associativity and an identity element make regrouping partial results meaningful.
A parallel reduction may group values differently, so its combine operation should be associative for equivalent results and have a suitable identity value. Floating-point addition can vary slightly with grouping. Avoid reducers with hidden side effects because execution order may not be stable.
What should an async Python task do when it receives cancellation?Release owned resources in cleanup and normally propagate cancellation after cleanup.
Cancellation is delivered at an await point. Use finally blocks or async context managers to close resources, then re-raise CancelledError unless there is a deliberate reason to suppress it. A blocking synchronous call may not respond promptly, so keep the event loop cooperative and bound background work.
What is the first step when a Python test fails intermittently?Capture the seed and environment, then isolate and repeatedly run the smallest failing test.
Treat the failure as evidence of an uncontrolled input. Record test order, random seed, runtime, timing, and environment; run the test alone and repeatedly. If it only fails in a suite, inspect shared fixtures, globals, ports, environment patches, clocks, and unawaited tasks before adding retries.
How do async def and standard def routes differ in FastAPI?Async routes run on the event loop; sync routes are generally dispatched to a worker thread pool.
An async route can yield during nonblocking I/O, allowing the event loop to serve other work. A normal def route is typically run in a thread pool. Calling blocking I/O inside async def blocks the event loop; using async syntax alone does not improve CPU-bound work. Choose an execution model based on the library and bottleneck.
Why is one global SQLAlchemy Session unsafe in an async FastAPI service?A Session carries mutable identity-map and transaction state and is not safe for concurrent requests.
Concurrent coroutines can interleave operations on the same Session, mixing transaction state and identity-map contents. Create a session per request or task, scope its transaction clearly, and size the connection pool across all worker processes and replicas. A global Engine/pool is different from a shared mutable Session.
Distributed Systems
Subject guidesWhat does vector-clock incomparability represent?Concurrent histories under the vector clock identity and propagation model.
If neither vector is component-wise less than the other, neither history contains all represented knowledge of the other. This does not establish physical-time order or choose a globally agreed winner.
Where must a fencing token be enforced?At the destination, atomically with the protected effect.
The destination rejects generations older than its highest accepted token. A lease does not stop a paused worker, and a fence cannot reject an expired generation it has not yet learned is superseded.
Why are Kafka offsets and commit timing so important?Offsets are the durability checkpoint. Commit too early and you lose work; commit too late and you duplicate it.
Kafka commits represent when the consumer believes work has been finished. If the offset is committed before the business effect is truly durable, a crash can lose data. If it is committed only after a delay, the application may re-process messages when the consumer restarts. The correct strategy is to commit only after the state change is stored successfully and the work is idempotent enough to recover from retries.
How does a transactional outbox make event publishing reliable?Persist the business change and an event record together, then publish the event asynchronously.
A database transaction writes both the business state and an outbox row. A separate publisher retries delivery from that durable row. This avoids the gap where a database commit succeeds but broker publication fails. Delivery can still be repeated, so consumers should deduplicate by a stable event ID.
How do you prevent Kafka CommitFailedException when processing is slow?Keep consumer liveness within max.poll.interval.ms and commit only after durable work.
If processing exceeds max.poll.interval.ms, the group may consider the member failed and reassign its partitions; a later commit from the old generation is rejected. Reduce records per poll, process with bounded workers while preserving partition ordering, pause/resume appropriately, or adjust the interval based on measured worst-case work. Keep the fix from merely delaying failure detection indefinitely.
What changes with acks=all and min.insync.replicas=2 during a broker partition?The producer may reject writes when fewer than two replicas remain in the in-sync set.
With three brokers and min.insync.replicas=2, acks=all requires the current in-sync replica set to meet the minimum. If the ISR falls to one, writes are rejected rather than acknowledged with reduced replication. acks=1 favors availability but risks losing leader-only writes if that leader fails before replication.
Unix
Subject guidesWhat can a subprocess inherit across exec?Environment strings and open descriptors not marked close-on-exec.
Construct a deliberate environment and descriptor allowlist. Descriptors grant capabilities to files, sockets, or pipes; inherited writers can delay EOF and inherited secrets can leak to less-trusted children.
What does atomic file replacement leave unchanged for existing readers?An already open descriptor still refers to the old file object.
Write a complete temporary file on the same filesystem and replace the pathname. New opens see the replacement; existing descriptors keep the old object. Durability and concurrent-writer coordination are separate guarantees.
Why does pipefail matter in shell scripts?Without pipefail, a pipeline can appear successful even when one command in the middle failed.
When you pipe commands together, the shell normally reports the exit status of the last command. That hides failures earlier in the chain. Setting pipefail makes the pipeline fail if any stage fails, which is critical for build automation and production scripts where silent partial failures create huge operational risk.
Why use exec in a container entrypoint script?Replacing the shell with the service improves signal delivery and exit-code propagation.
Without exec, the shell can remain as the parent process and may not forward termination signals as intended. `exec service ...` replaces the shell, making the service the main process so it receives the container stop signal directly and its exit status is reported. A wrapper supervising multiple children must explicitly forward signals and reap them.
When should you use grep, sed, or awk?Use grep to select lines, sed for stream edits, and awk for field-based filtering and calculations.
grep selects matching lines; sed applies stream transformations such as substitutions; awk processes records and fields. Quote patterns for the shell, test edits on copied input, and do not treat default awk splitting as a full CSV parser. For structured formats or complex quoting, use a format-aware parser.
How do you debug a shell script without leaking secrets?Trace selectively, preserve quoting and exit status, and avoid dumping sensitive expanded arguments.
Check the intended interpreter and run a syntax check first. Enable xtrace only around the suspect section because it prints expanded values; redirect diagnostics securely and mask credentials. Reproduce with controlled input, inspect each command status, and use ShellCheck to catch common quoting and portability issues.
How do you preserve exit failures through a shell pipeline?Use pipefail where supported and handle expected no-match statuses separately from actual errors.
Many shells report only the last pipeline command status. In Bash, `set -o pipefail` makes a pipeline fail when a stage fails. grep status 1 often means no match rather than a tool error, so scripts should distinguish that expected result from status 2 or an upstream failure.
How do you check whether a service is listening on a port?Inspect local socket state and bind address before changing firewall policy.
On Linux, `ss -lntup` lists listening sockets; `netstat` may be available via net-tools on older systems. Confirm the process, address, and network namespace. A service bound only to 127.0.0.1 is not externally reachable; also check container port mapping and host policy.
What can tcpdump reveal when a TCP connection times out?Packet direction and handshake behavior help locate whether loss occurs before or after the destination.
Capture narrowly at the client and, if possible, server. A SYN leaving without a reply suggests routing or filtering; a reset indicates an active rejection or no listener; a completed handshake moves investigation toward TLS or the application protocol. Packet captures can expose sensitive metadata or payloads, so limit capture scope and protect files.
How do TCP and UDP differ when debugging a service?TCP establishes an ordered byte stream; UDP sends datagrams without delivery acknowledgement from the transport.
TCP connection establishment and retransmission make a port-connectivity test meaningful, but application message boundaries still need framing. UDP has no handshake, so silence may mean a dropped packet, invalid request, or a service that does not answer probes. Test using a valid protocol request and inspect both ends when possible.
Why can grep make a shell script exit even though nothing is broken?grep returns status 1 when there are no matches, which may trigger strict shell error handling.
grep commonly exits 0 when it finds a match, 1 when it finds none, and 2 for an error. With `set -e`, an expected no-match status can terminate a script unless handled intentionally. Distinguish absence from malformed input or permission failures rather than suppressing every status.
Can awk safely parse arbitrary CSV by splitting on commas?Not generally; quoted fields can contain commas and require CSV-aware parsing.
Default awk field splitting does not implement CSV quoting and escaped-quote rules. It can work for a deliberately simple delimiter-separated file with no quoted delimiters, but use a CSV-aware parser for general CSV. Verify input format before writing a transformation that could silently shift columns.
What does an outgoing TCP SYN with no reply suggest?The connection attempt left the observed point, but no response returned there.
It narrows the investigation but does not identify one root cause: route failure, filtering, destination outage, asymmetric routing, or capture at the wrong interface can all look similar. Capture at both ends, check socket listeners and network policy, and correlate with route and firewall telemetry.
Why is a UDP port scan inconclusive about application health?UDP has no connection handshake and applications may not answer an invalid or empty probe.
Unlike TCP, UDP does not establish a transport connection before sending a datagram. A missing response can mean filtering, packet loss, an invalid request, or an application that does not reply. Use a valid protocol-level health check and capture at sender and receiver when diagnosing the path.
How can you tell a DNS failure from a TCP connectivity failure?Resolve the name from the failing runtime, then test the returned address and port separately.
Use the system resolver path, for example getent hosts, and compare with a direct DNS query. If a correct address resolves but the connection fails, investigate route, listener, firewall, or protocol behavior. Run diagnostics inside the same container or namespace as the application because resolver configuration may differ.
Why can a Linux filesystem be full when du shows free space?Inodes may be exhausted, or deleted files may still be held open by running processes.
Compare df -h with df -i. If block usage and directory totals disagree, inspect open-but-deleted files with lsof +L1. A process retains allocated blocks until it closes the file; restart or signal the owning service through its safe lifecycle after confirming the file is disposable.
Why can epoll handle many mostly-idle sockets more efficiently than select?epoll tracks interest and reports readiness changes instead of requiring repeated full-set scans.
select requires rebuilding and scanning descriptor sets on each wait and has platform-specific descriptor limits; poll also examines a supplied list. epoll maintains kernel-side interest and ready structures, which suits large mostly-idle sets. It does not remove per-connection memory costs, application scheduling, or edge-triggered drain requirements.
What does a large TCP TIME_WAIT count mean?TIME_WAIT is part of safe TCP teardown; verify actual ephemeral-port pressure before tuning sysctls.
TIME_WAIT helps prevent delayed packets from an old connection from contaminating a new one. A high count can be normal. Diagnose port exhaustion by checking outbound tuple reuse, NAT limits, ephemeral port range, and connection pooling. tcp_tw_reuse semantics vary by kernel and are not a universal first fix.
Databases
Subject guidesWhat should you inspect after CREATE INDEX CONCURRENTLY fails?Check active work and catalog validity before dropping or retrying.
Concurrent builds use multiple phases and can leave an invalid index. Inspect the server error and pg_index readiness/validity, waits, and transactions; do not assume the operation was atomic or load-free.
Why does a timestamp cursor need a unique tie-breaker?Equal timestamps otherwise make continuation skip or repeat peers.
Carry the full ordering tuple, such as created_at and ID, and match its direction in the continuation predicate. Stable continuation still does not freeze membership across requests.
Why does a relational table need a primary key?A primary key gives each row a stable identity; it does not replace domain-level uniqueness constraints.
A primary key lets the database and applications refer to one row unambiguously and lets foreign keys express relationships. Add separate unique constraints for business rules such as one account per email. A generated ID alone does not prevent duplicate domain entities.
Why can a long PostgreSQL transaction delay vacuum cleanup?An old transaction snapshot may still need row versions that newer transactions have replaced.
PostgreSQL MVCC keeps row versions visible to active snapshots. A long-running transaction can hold an old snapshot open, so vacuum cannot yet remove some dead versions. Bound transaction lifetimes and investigate idle-in-transaction sessions when table bloat grows.
How does the InnoDB primary key affect secondary indexes?InnoDB secondary-index entries carry the primary-key value used to find the clustered row.
InnoDB organizes table rows by the clustered primary key. Secondary indexes store their indexed columns plus the primary-key value, so a query requesting columns absent from the secondary index may need a second lookup. Wide primary keys therefore increase the footprint of every secondary index.
How are Oracle analytic functions different from GROUP BY?Analytic functions calculate across a partition while keeping each input row in the result.
GROUP BY collapses rows into one row per group. An analytic function uses OVER with partition, ordering, and frame rules to calculate a value while preserving row detail. Specify a deterministic ordering and explicit frame for running totals when peer-row behavior would matter.
How do you find the third-highest distinct salary in SQL?Use DENSE_RANK for distinct values and state whether you want salary values or employee rows.
Filter out NULL salaries, compute DENSE_RANK() OVER (ORDER BY salary DESC), then select rank 3. DENSE_RANK treats equal salaries as the same rank. PostgreSQL, MySQL 8+, and Oracle support this window-function approach; if you instead mean the third row, use ROW_NUMBER with a deterministic tie-breaker.
What is the difference between WHERE and HAVING?WHERE filters input rows before grouping; HAVING filters groups after aggregation.
Use WHERE to remove rows before GROUP BY, such as excluding inactive employees. Use HAVING to filter aggregate results, such as departments with COUNT(*) greater than five. Moving a condition between them can change both meaning and query work.
Why did a SQL join unexpectedly multiply my totals?A one-to-many join changes row grain; multiple child joins can multiply each other.
Check the cardinality of each join. Joining one order to several lines produces multiple rows per order; joining another one-to-many table can multiply those rows again. Aggregate each relation to the intended grain before joining or use EXISTS when you only need to test presence. DISTINCT is not a reliable repair for incorrect join logic.
How do database functions differ from stored procedures?Functions typically return values; procedures are invoked as operations, with engine-specific transaction rules.
A function is commonly used as an expression or query result and returns a value or table. A procedure is invoked to perform an operation and may accept output parameters. Triggers run implicitly. Transaction control differs by engine, so keep commit ownership explicit and test routines against the target database/version.
How does top-N syntax differ across PostgreSQL, MySQL, and Oracle?PostgreSQL and MySQL commonly use LIMIT; Oracle supports FETCH FIRST and legacy ROWNUM patterns.
PostgreSQL and MySQL support ORDER BY with LIMIT; standard FETCH FIRST syntax is also available in modern versions. Oracle supports FETCH FIRST in current versions; older ROWNUM queries must sort in an inner query before limiting in an outer query. Always specify deterministic ordering and test the exact target version.
Why can COUNT(column) differ from COUNT(*)?COUNT(column) excludes NULL values; COUNT(*) counts input rows.
COUNT(*) counts each row in the group regardless of column values. COUNT(column) counts only rows where that expression is non-NULL. When aggregates look low, check nullability and join multiplication before changing the query.
Why can’t a window-function rank usually be filtered in WHERE?Window values are computed after WHERE in logical query processing.
WHERE filters source rows before window calculations are available. Put the window expression in a common table expression or derived table, then filter its rank in the outer query. This also makes the ranking input set explicit.
Why can a database trigger make an application write hard to debug?The statement has side effects that are not visible at its call site.
A trigger can modify other rows or tables implicitly during an insert or update. That makes the visible application statement an incomplete description of the transaction and can add locking or recursion. Document and test trigger effects, or move orchestration to an explicit routine/service when hidden behavior harms operability.
What is a safe application response to a database deadlock victim error?Retry the whole idempotent transaction within a bounded policy, not just an arbitrary statement.
A deadlock detector aborts one transaction so another can progress. Capture lock and query evidence, then retry the whole business transaction only if its effects are safe to repeat. Use bounded attempts with jitter, consistent resource ordering, and idempotency for any external side effects.
How do you confirm and fix an ORM N+1 query?Count repeated statements per request, then batch-load without changing result cardinality.
Trace or log normalized SQL for one request and look for the same child lookup repeated once per parent row. Replace the loop with an eager/batch load or a query at the correct grain. Verify query count and returned rows; a broad join can fix round trips while accidentally multiplying results.
How can write skew occur under snapshot or repeatable-read isolation?Two transactions can read the same invariant and update disjoint rows, so row-level conflicts do not detect the violation.
If each transaction sees a snapshot where another row satisfies a rule, they may update different rows and both commit, leaving the combined invariant false. Use a constraint, lock a shared coordination row, or use serializable isolation with whole-transaction retry. Exact Repeatable Read semantics differ by engine.
Can an index on (a, b, c) efficiently serve a query filtering only b and c?Usually the leading-column prefix matters; validate any skip-scan behavior on the target engine.
A composite B-tree is generally organized by its leading column, so omitting a can prevent efficient use of the index for b/c-only predicates. Some engines and versions may use skip scans under particular statistics, but do not assume it. Compare a candidate (b, c) index with the existing index using representative plans and write-cost measurements.