This article concerns real-time and knowledgeable C Scenario-Based Questions 2025. It is drafted with the interview theme in mind to provide maximum support for your interview. Go through these C Scenario-Based Questions 2025 to the end, as all scenarios have their importance and learning potential.
To check out other Scenarios Based Questions:- Click Here.
Disclaimer:
These solutions are based on my experience and best effort. Actual results may vary depending on your setup. Codes may need some tweaking.
1) A service written in C is leaking memory after a feature rollout—how would you stabilize and triage without code changes?
- I’d first contain blast radius: reduce traffic, add safe restarts, and isolate the process so the host stays healthy.
- I’d turn on lightweight runtime telemetry (RSS trends, allocation counts) to see leak shape over time.
- I’d compare pre- and post-release behaviors to narrow the suspect path quickly.
- I’d review long-lived objects and caches to check if “add but never free” patterns slipped in.
- I’d sample live heap snapshots or logs to find which request types grow memory.
- I’d add temporary caps on cache sizes and disable the new path via a kill-switch if available.
- I’d plan a rollback if stabilization isn’t holding, then fix the root cause with a small, audited patch.
2) You inherit a C library used by multiple teams; ABI breaks are causing runtime crashes—how do you regain trust?
- I’d define a strict versioning policy and promise not to break existing symbols without a major bump.
- I’d add symbol visibility rules so only intended APIs are exported.
- I’d introduce compatibility shims for the most used older calls.
- I’d document struct layouts and padding rules to prevent silent layout drift.
- I’d add an ABI check in CI that compares headers and symbol maps before release.
- I’d publish a clear migration guide with examples of safe replacements.
- I’d stage releases with beta tags so downstreams can validate before we lock.
3) On a 32-bit to 64-bit migration, your C program corrupts data intermittently—what pitfalls do you target first?
- I’d look for pointer-to-int casts where width changes break assumptions.
- I’d review struct packing and alignment, especially around pointers and size_t fields.
- I’d check file offsets and time types for truncation and sign issues.
- I’d scan printf/scanf format strings for mismatches with wider types.
- I’d examine cross-process protocols where field sizes were “implied” not defined.
- I’d test boundary cases with very large indices and buffer sizes.
- I’d add static analysis to flag unsafe casts and suspicious arithmetic.
4) Real-time system spikes cause missed deadlines—how do you make a C module more predictable?
- I’d map the hot path and remove dynamic allocation in the deadline window.
- I’d prefer fixed-size buffers and pre-initialized pools to avoid jitter.
- I’d bound loops and avoid unbounded retries or backoffs.
- I’d pick algorithms with stable O(1)/O(log n) behavior under load.
- I’d reduce syscalls and context switches inside the critical section.
- I’d set clear priorities and avoid priority inversion with careful locking.
- I’d measure worst-case latency, not averages, before and after changes.
5) Your C service crashes only under heavy concurrency—how do you hunt the race without drowning in logs?
- I’d reproduce with a stress profile that amplifies the timing window.
- I’d shrink the suspect area by toggling features until the crash pattern changes.
- I’d add minimal, timestamped markers around shared data accesses.
- I’d check for double-free, use-after-free, and non-atomic reads of shared flags.
- I’d simplify locking: one owner, one policy, and clear lock order to avoid cycles.
- I’d create a tiny standalone test that mimics the contested access.
- I’d keep fixes surgical and write a regression test that hammers the same path.
6) Two teams want static vs dynamic linking for your C SDK—how do you decide?
- I’d start from consumer constraints: footprint, update cadence, and platform rules.
- Static linking helps with single-file deploys and no external deps.
- Dynamic linking helps patch security issues without rebuilding apps.
- Static can bloat binaries; dynamic can create “works on my machine” issues.
- Licensing and symbol visibility may push one way or the other.
- For many clients, I’d ship both plus a stable C API layer and versioned SONAME.
- I’d document the trade-offs so teams choose knowingly.
7) Your embedded C code must run with “no malloc” policy—how do you design safely?
- I’d size all buffers upfront with clear headroom for worst-case inputs.
- I’d use ring buffers and object pools for predictable reuse.
- I’d validate all indices and lengths before touching memory.
- I’d precompute tables and constants at build time where possible.
- I’d design state machines with explicit states instead of ad-hoc flags.
- I’d add runtime asserts that can be compiled out in production builds.
- I’d monitor stack depth to avoid silent overflows.
8) A new feature needs file I/O speedups—what would you try before rewriting in another language?
- I’d batch reads/writes to reduce syscall overhead.
- I’d use buffered I/O wisely and align to the filesystem block size.
- I’d evaluate memory-mapped I/O if access patterns suit it.
- I’d avoid tiny syncs; coalesce flushes where durability rules allow.
- I’d pre-allocate files to prevent fragmentation during growth.
- I’d profile actual I/O wait vs CPU so we fix the real bottleneck.
- I’d confirm that the storage and mount options aren’t the hidden culprit.
9) Your team keeps hitting undefined behavior bugs—how do you reduce UB risk in a C codebase?
- I’d define a strict subset: no wild pointer casts, no aliasing tricks.
- I’d turn on maximum warnings and treat them as errors.
- I’d run sanitizers regularly in CI to catch UB early.
- I’d replace hand-rolled macros with safer inline functions.
- I’d document alignment, lifetime, and ownership rules in headers.
- I’d add small unit tests around any code that relies on compilers’ specifics.
- I’d conduct targeted code reviews focused on UB hotspots.
10) Logging in C flooded disks during an incident—how do you make observability safer?
- I’d set log budgets and rate limits so noise can’t take systems down.
- I’d separate user-path logs from debug logs with clear levels.
- I’d log structured key facts, not entire payloads.
- I’d include correlation IDs to stitch requests across modules.
- I’d keep logging non-blocking and drop-tolerant under backpressure.
- I’d rotate and compress by size and time with retention policies.
- I’d rehearse “incident mode” settings to raise signal without chaos.
11) Your C module must integrate with Python—how do you keep the boundary safe and simple?
- I’d keep the C surface area small and stable, just the critical loops.
- I’d pass plain C types and lengths; avoid hidden ownership traps.
- I’d document who allocates and who frees for every pointer.
- I’d validate inputs on the C side even if Python checked earlier.
- I’d return clear error codes and map them to Python exceptions.
- I’d test with representative data sizes from Python callers.
- I’d version the interface so upgrades don’t surprise users.
12) After a rollback, you fear partial state corruption—what’s your C-level recovery plan?
- I’d verify on-disk formats match the downgraded version’s expectations.
- I’d add sanity checks before trusting persisted counters and lengths.
- I’d create repair routines that rebuild indexes from source truth.
- I’d gate risky operations until validation passes.
- I’d log any auto-repairs for audit and follow-up.
- I’d run consistency checks as part of startup, not later.
- I’d document a clear forward-only rule if backward migration is unsafe.
13) Security asks for hardened builds—what changes make sense for C services?
- I’d compile with defenses like stack protections and control-flow guards where available.
- I’d minimize the attack surface by hiding non-API symbols.
- I’d drop privileges early and sandbox risky parts if possible.
- I’d validate every external input and bound every buffer.
- I’d avoid risky string routines in favor of length-aware variants.
- I’d keep third-party deps updated and pinned.
- I’d add fuzzing on inputs that parse complex formats.
14) Customers report “works on Linux, fails on Windows”—how do you chase portability issues?
- I’d review path, newline, and charset assumptions.
- I’d check struct packing and calling conventions across compilers.
- I’d replace non-portable APIs with standard ones or adapters.
- I’d ensure sockets, time, and signals are abstracted behind a thin layer.
- I’d use consistent integer widths and explicit endianness handling.
- I’d set up cross-platform CI so we never regress.
- I’d add small smoke tests for each OS-specific behavior.
15) Your C library uses callbacks heavily; a client blames you for reentrancy crashes—how do you respond?
- I’d document whether callbacks can reenter and what’s allowed inside them.
- I’d ensure we never call user callbacks while holding internal locks.
- I’d snapshot callback pointers under a lock, then invoke without locks.
- I’d provide a “defer” mode for clients who want callbacks on a safe thread.
- I’d clarify ownership of user data passed to callbacks.
- I’d add tests that simulate reentrancy and cancellation.
- I’d offer sample wrappers showing recommended patterns.
16) A hot loop in C is CPU-bound—how do you get a safe speedup without micro-obsessing?
- I’d measure first to confirm where time actually goes.
- I’d pick simpler data layouts that are cache-friendly.
- I’d remove unnecessary branches or move them out of the loop.
- I’d hoist invariant computations and precompute tables.
- I’d try chunked processing to leverage modern CPUs better.
- I’d keep correctness tests close while iterating.
- I’d stop once the gain is meaningful and stable under real loads.
17) Your socket code drops messages during bursts—what do you adjust in design?
- I’d accept that bursts happen and add bounded queues with backpressure.
- I’d batch sends/receives where protocol allows.
- I’d avoid blocking the main loop with slow handlers.
- I’d separate control and data paths to keep control responsive.
- I’d add lightweight drop metrics to see when buffers overflow.
- I’d tune timeouts thoughtfully rather than “just increase”.
- I’d document throughput vs latency trade-offs for the team.
18) A third-party C dependency is abandonware—how do you de-risk?
- I’d fork or wrap it behind a narrow interface we control.
- I’d audit the code for obvious security and portability issues.
- I’d add tests that lock in our expected behaviors.
- I’d pin versions and vendor the code for build determinism.
- I’d plan a migration path to a maintained alternative.
- I’d watch for CVE chatter and triage quickly if one lands.
- I’d keep stakeholders informed on the exit timeline.
19) Team debates “one big header” vs modular headers—how do you set a direction?
- I’d prefer small, focused headers with clear ownership.
- I’d reduce include chains to prevent slow and fragile builds.
- I’d ensure each public header is self-contained and guarded.
- I’d split internal vs public headers to avoid leaking details.
- I’d make naming predictable so discoverability is easy.
- I’d add an include-what-you-use check in CI.
- I’d document stable API and mark internal parts clearly.
20) Error handling is inconsistent across modules—how do you standardize?
- I’d agree on a return-code model and reserve ranges per module.
- I’d pair codes with short, human-readable messages.
- I’d ensure functions never mix “return code” and “errno” ambiguously.
- I’d avoid silent retries and always log at the decision point.
- I’d create helpers to map errors to consistent logs and metrics.
- I’d write a one-pager so new code follows the same style.
- I’d add tests that simulate failures to verify handling paths.
21) Your build is flaky across compilers—what policy keeps you safe?
- I’d define the compilers and versions we support on each platform.
- I’d require warnings-as-errors and a shared warning baseline.
- I’d run CI on at least two compilers to catch differences.
- I’d freeze toolchains for releases and update deliberately.
- I’d track feature usage and avoid compiler-specific extensions by default.
- I’d document exact flags so local builds match CI.
- I’d keep reproducible builds to help debugging.
22) The team wants to add threads to a formerly single-threaded C app—how do you phase it in safely?
- I’d start with read-mostly parts that benefit from parallelism.
- I’d define ownership so each thread has clear responsibilities.
- I’d pick simple synchronization primitives first, then evolve.
- I’d avoid sharing complex structures; pass messages instead.
- I’d add thread-aware tests that run under load.
- I’d keep tracing lightweight to observe contention early.
- I’d stop if complexity outgrows the actual gains.
23) Customers ask for a plugin system—what does a safe C plugin contract look like?
- I’d define a versioned, C-only ABI with strict types.
- I’d specify lifecycle hooks: init, run, shutdown, and error semantics.
- I’d keep the host owning all memory unless explicitly delegated.
- I’d require plugins to declare capabilities at load time.
- I’d sandbox or restrict plugins to protect the host.
- I’d log plugin boundaries and failures distinctly.
- I’d ship a reference plugin as the golden example.
24) Intermittent checksum mismatches appear in your C storage layer—where do you look first?
- I’d ensure all I/O is using the intended endianness consistently.
- I’d check uninitialized padding in structs being written to disk.
- I’d verify partial write handling and crash-safe sequencing.
- I’d compare checksum code across read/write paths for symmetry.
- I’d test with power-loss style interruptions to expose ordering bugs.
- I’d confirm no background scrubber “fixes” good data incorrectly.
- I’d add a repair tool for small, contained corruption cases.
25) A critical C process sometimes hangs during shutdown—how do you make exits clean?
- I’d define a clear shutdown sequence and responsibilities.
- I’d make signal handlers minimal and just set flags.
- I’d join threads with timeouts and report which one blocks.
- I’d ensure all queues stop accepting new work early.
- I’d close external resources in a known order.
- I’d keep shutdown idempotent so it tolerates retries.
- I’d test shutdown under load, not only when idle.
26) You must expose metrics from a C service—how do you avoid performance and accuracy traps?
- I’d pick a small set of counters that actually guide decisions.
- I’d keep collection lock-free where possible or use per-thread buffers.
- I’d expose rates and latencies with clear units and percentiles.
- I’d sample sparingly on hot paths to avoid overhead.
- I’d validate metrics against logs during incidents.
- I’d document each metric’s meaning so alerts are sane.
- I’d keep scraping resilient to brief pauses or hiccups.
27) A library uses global state heavily—how do you reduce surprises?
- I’d encapsulate globals behind accessor functions.
- I’d allow explicit init and teardown so users control lifetime.
- I’d avoid hidden singletons in favor of passed contexts.
- I’d make state thread-safe or clearly single-threaded.
- I’d add tests that run multiple independent instances.
- I’d document what is and isn’t shared across calls.
- I’d plan a gradual de-globalization in new versions.
28) Your C parser crashes on malformed inputs from the field—how do you harden it?
- I’d validate lengths and bounds before reading any field.
- I’d reject unreasonable sizes early with clear errors.
- I’d cap recursion or nesting depth to avoid stack issues.
- I’d fuzz with real-world corpora plus random mutations.
- I’d separate parse and execute phases to limit damage.
- I’d keep parsing state explicit to simplify recovery.
- I’d log minimal context for later reproduction.
29) The team wants to switch from makefiles to a new build system—what do you insist on?
- I’d require fast, incremental builds that scale to the repo.
- I’d want first-class support for multiple compilers and platforms.
- I’d need reproducible outputs for releases and debugging.
- I’d insist on simple dependency declarations and visibility rules.
- I’d want easy integration with testing and static analysis.
- I’d plan a staged migration with a clear fallback.
- I’d document the developer workflow so productivity doesn’t dip.
30) Your binary size is too large for your target—how do you slim it down sensibly?
- I’d strip symbols from release binaries while keeping separate debug files.
- I’d remove unused features via build-time flags.
- I’d prefer smaller data structures and avoid duplicate tables.
- I’d share common code across modules rather than copy-paste.
- I’d review inlining decisions that balloon code size.
- I’d compress assets and consider lazy loading where acceptable.
- I’d track size in CI to catch regressions early.
31) A partner requests synchronous APIs, but you prefer async—how do you offer both without confusion?
- I’d implement one core async engine and wrap a sync layer on top.
- I’d make timeouts explicit so sync calls don’t hang forever.
- I’d document threading expectations and reentrancy clearly.
- I’d ensure both paths share the same validation and error codes.
- I’d test equivalence: same input, same outcome across styles.
- I’d advise partners on where sync is fine vs risky.
- I’d mark any performance caveats in the sync layer.
32) Your team struggles with pointer ownership—how do you make it obvious?
- I’d standardize “create/retain/release” naming that signals ownership.
- I’d return const pointers when callers must not free.
- I’d add API docs with one-line ownership rules per function.
- I’d avoid transferring ownership mid-function unexpectedly.
- I’d add lightweight lifetime checks in debug builds.
- I’d wrap raw pointers in small handles where helpful.
- I’d review any function that returns borrowed memory.
33) Load tests show long tail latencies—how do you shave the tail in C?
- I’d find contention points and reduce shared state.
- I’d isolate slow operations on separate threads or queues.
- I’d cache hot computations with clear eviction rules.
- I’d pre-warm critical paths before traffic arrives.
- I’d add timeouts and fallbacks so outliers don’t poison the pool.
- I’d monitor p95/p99 separately and set goals for each.
- I’d re-test with realistic burst patterns, not just steady load.
34) Your CLI tool in C confuses users—how do you improve UX without heavy frameworks?
- I’d provide short and long flags with clear help output.
- I’d support config files and environment overrides predictably.
- I’d return non-zero codes with friendly messages on errors.
- I’d add dry-run mode to show what would happen.
- I’d keep output stable so scripts don’t break silently.
- I’d include examples for common tasks users actually face.
- I’d version the CLI behavior and note breaking changes.
35) You must expose a stable file format—how do you future-proof it?
- I’d define endian and alignment explicitly in the spec.
- I’d include a version field and reserved space for growth.
- I’d validate checksums and lengths on read.
- I’d avoid encoding pointers or implicit sizes.
- I’d publish sample files and a conformance test.
- I’d keep the writer strict and the reader tolerant.
- I’d document upgrade paths between versions.
36) A watchdog keeps restarting your C daemon—what do you check first?
- I’d confirm if exits are crashes, asserts, or clean exits misread as failures.
- I’d review startup time; maybe the watchdog times out too early.
- I’d scan for blocking operations in the main loop.
- I’d check resource limits like file descriptors and memory.
- I’d ensure signals are handled and not terminating the process.
- I’d inspect logs just before exit for the real culprit.
- I’d add minimal health checks the watchdog can trust.
37) Your team proposes heavy macro magic—where do you draw the line?
- I’d allow small, safe macros for constants and guards.
- I’d prefer inline functions for type safety and debugging.
- I’d ban macros that alter control flow in surprising ways.
- I’d keep error-handling macros simple and readable.
- I’d require macro names to shout their intent clearly.
- I’d document any macro that touches user arguments twice.
- I’d measure compile-time and debug impact before adopting.
38) A critical path uses variable-length arrays—what risks do you consider?
- I’d worry about stack overflows with large inputs.
- I’d consider portability since not all compilers handle them equally.
- I’d prefer fixed bounds or heap with checks for big sizes.
- I’d validate sizes before allocation to avoid wraparounds.
- I’d test with extreme values to see failure modes.
- I’d document limits so callers don’t exceed them.
- I’d keep alternatives ready for constrained targets.
39) You need to load configuration safely at runtime—what principles guide you?
- I’d parse defensively and reject unknown or conflicting options.
- I’d prefer atomic reloads so half-applied configs don’t leak in.
- I’d validate ranges and dependencies before accepting changes.
- I’d log exactly what changed and why it was accepted or rejected.
- I’d keep defaults sane so missing fields don’t break startup.
- I’d separate user syntax from internal representation.
- I’d provide a “check-only” mode for operators.
40) A vendor asks for “zero-copy” integration—how do you set safe expectations?
- I’d clarify alignment, lifetime, and mutability of the shared buffers.
- I’d guard against aliasing surprises by documenting access rules.
- I’d ensure we can fall back to a copy if conditions aren’t met.
- I’d verify error paths don’t leak or double-free shared memory.
- I’d add canary checks around the shared region.
- I’d benchmark to prove the gain is real under load.
- I’d refuse zero-copy where correctness becomes fragile.
41) Your C service must run inside containers—what do you watch out for?
- I’d confirm resource limits and ensure we handle throttling.
- I’d write to stdout/stderr for logs and let the platform collect them.
- I’d avoid relying on host paths or device specifics unless mounted.
- I’d keep time, locale, and DNS assumptions explicit.
- I’d expose health endpoints for liveness and readiness.
- I’d ensure graceful shutdown on container stop signals.
- I’d test cold starts and rolling updates realistically.
42) A junior dev proposes “just add a mutex everywhere”—how do you mentor them?
- I’d show how coarse locks can serialize the whole app.
- I’d start with data ownership and reduce sharing first.
- I’d choose appropriate lock granularity where sharing remains.
- I’d teach lock ordering to avoid deadlocks.
- I’d introduce read-write locks when reads dominate.
- I’d suggest message passing if it simplifies the model.
- I’d measure contention to guide improvements.
43) Your CRC check sometimes passes bad data—what might be wrong?
- I’d check the polynomial and initial values match on both ends.
- I’d confirm byte order and reflection settings are consistent.
- I’d verify we’re checksumming the same fields and lengths.
- I’d ensure no padding or uninitialized memory sneaks into the CRC.
- I’d test known vectors from a reference implementation.
- I’d log the intermediate state for mismatched cases.
- I’d lock the configuration once verified to prevent drift.
44) You must support graceful feature flags in a C service—what’s your approach?
- I’d separate flag evaluation from business logic.
- I’d keep flags typed and validated at load.
- I’d default to safe behavior if a flag is missing.
- I’d avoid flag checks in hot inner loops when possible.
- I’d log flag states at startup and on change.
- I’d test both flag on/off paths in CI.
- I’d prune old flags so code stays clean.
45) A legacy C tool has grown huge—how do you break it into maintainable parts?
- I’d identify natural seams: I/O, parsing, compute, output.
- I’d define clear C interfaces between modules with minimal types.
- I’d extract one module at a time with tests.
- I’d keep the main program as a thin orchestrator.
- I’d remove global state as modules are split.
- I’d document each module’s contract and limits.
- I’d stop once complexity is under control.
46) Your allocator usage spikes memory fragmentation—what mitigations help?
- I’d group similar-lifetime objects to free in batches.
- I’d use pools or arenas for short-lived allocations.
- I’d align allocations for the platform to reduce waste.
- I’d avoid frequent resize patterns that churn memory.
- I’d measure fragmentation with targeted tests.
- I’d consider custom allocators only if general ones fail.
- I’d cap caches so they don’t hoard memory.
47) A critical library must be dual-licensed internally—how do you keep it simple?
- I’d keep one codebase with a clear, documented license switch.
- I’d separate any optional components that trigger different terms.
- I’d add headers that state licensing per file.
- I’d automate license checks in CI to avoid mistakes.
- I’d publish a consumer guide explaining what’s allowed.
- I’d avoid dependencies that complicate the licensing story.
- I’d review legal text with stakeholders before release.
48) Your C program must be scriptable by users—what embedding strategy feels safe?
- I’d expose a small, stable C API that bindings can call.
- I’d isolate the scripting engine so crashes don’t kill the host.
- I’d validate user inputs at the boundary, not deep inside.
- I’d offer time and memory limits for user scripts.
- I’d keep the host authoritative on resources and state.
- I’d document safe examples users can start from.
- I’d log script errors clearly for support.
49) You need to guarantee order of durable writes—how do you reason about it?
- I’d define the durability contract precisely for users.
- I’d sequence writes and metadata updates in a proven order.
- I’d avoid partial updates by using temporary files or journals.
- I’d bound the window where data is vulnerable to power loss.
- I’d test with crash injection to validate recovery.
- I’d keep the code path short and well-reviewed.
- I’d document failure modes and repair steps.
50) The team wants faster startup—what are your first levers in C?
- I’d profile startup to see where time is truly spent.
- I’d lazy-init heavy subsystems after serving the first request.
- I’d reduce disk I/O by bundling or caching metadata.
- I’d cut dynamic linking bloat if it’s causing delays.
- I’d precompute configs and avoid expensive parsing.
- I’d parallelize independent init tasks where safe.
- I’d measure cold vs warm start to show progress.
51) Your service must run in low-memory environments—what patterns help?
- I’d choose compact data structures and reuse buffers.
- I’d avoid large on-heap graphs in favor of flat arrays.
- I’d stream data instead of loading everything at once.
- I’d shrink logs and disable verbose tracing by default.
- I’d cap caches and back them by disk when acceptable.
- I’d provide “light mode” build options for features.
- I’d constantly watch peak RSS, not just averages.
52) An ops team requests “self-diagnostics” in your C app—what do you include?
- I’d add a status endpoint or CLI flag that reports health.
- I’d include recent errors, queue depths, and resource usage.
- I’d show config version and build info for quick support.
- I’d expose last successful external checks (like disk or network).
- I’d make it safe to call during load without heavy work.
- I’d redact secrets and keep output stable.
- I’d document how to read it during incidents.
53) Your C code must handle time zones and daylight changes—how do you stay sane?
- I’d store and compute in UTC internally.
- I’d convert to local time only at the edges for display.
- I’d avoid assuming fixed offsets due to daylight shifts.
- I’d treat timestamps as 64-bit and check for overflow.
- I’d keep libraries updated for time zone rules.
- I’d test around daylight transitions specifically.
- I’d log in UTC to simplify analysis.
54) A customer wants binary plugins from different compilers—how do you make that realistic?
- I’d define a C ABI that avoids compiler-specific features.
- I’d use simple calling conventions and plain structs.
- I’d freeze alignment and packing to known rules.
- I’d publish a conformance test that plugin builds must pass.
- I’d ship headers that avoid variadic or complex macros.
- I’d document supported compiler and OS combinations.
- I’d provide a reference build as a template.
55) Your config grows complex—how do you prevent “yaml engineering” in C products?
- I’d prefer small, composable options over giant nested blocks.
- I’d add schema validation so bad configs fail fast.
- I’d keep defaults sensible and visible.
- I’d deprecate old options with warnings before removal.
- I’d log effective config at startup for transparency.
- I’d provide examples for common real setups.
- I’d cut features that add confusion without value.
56) You must expose a streaming API—what guarantees do you commit to?
- I’d define order, delivery guarantees, and backpressure behavior.
- I’d document chunk sizes and heartbeat policies.
- I’d keep reconnection rules predictable with resume options.
- I’d make limits explicit so users design for them.
- I’d include metrics that reflect stream health.
- I’d write tests for slow consumers and flaky links.
- I’d keep error codes distinct for retry decisions.
57) A kernel-adjacent C component sees sporadic stalls—how do you reason about it?
- I’d check if we’re blocking on I/O or locks unintentionally.
- I’d measure scheduler delays and priority settings.
- I’d minimize cross-CPU chatter and cache-line ping-pong.
- I’d avoid heavy allocations in sensitive paths.
- I’d batch work to reduce syscall frequency.
- I’d test under real interrupt patterns, not synthetic ones.
- I’d capture timing traces that show precise wait points.
58) Your library needs international text support—how do you avoid surprises?
- I’d treat text as bytes plus explicit encoding, not raw char*.
- I’d validate input encoding and reject invalid sequences.
- I’d be careful with length vs byte count math.
- I’d avoid assuming case-folding or collation rules.
- I’d document exactly which encodings we support.
- I’d keep error messages clear when decoding fails.
- I’d test with mixed-language datasets.
59) You’re asked to add caching—how do you keep it from hiding bugs?
- I’d define cache keys and TTLs based on real access patterns.
- I’d verify correctness without cache first, then enable.
- I’d add metrics for hit/miss, evictions, and staleness.
- I’d avoid caching errors or partial results by mistake.
- I’d size the cache to avoid memory shocks.
- I’d make cache easy to disable for debugging.
- I’d test consistency across multiple processes.
60) The release process for your C project is chaotic—how do you calm it down?
- I’d set a predictable cadence and criteria for cutting releases.
- I’d require green CI, changelogs, and version bumps.
- I’d tag builds and publish artifacts reproducibly.
- I’d ship release notes that focus on impact and risks.
- I’d run a short stabilization window with targeted fixes only.
- I’d keep a rollback plan and practice it once.
- I’d gather post-release feedback to improve the next one.