Software Engineering Interview Questions

30 questions. Expand any one to see what the interviewer is really probing for and how to structure a strong answer, then practice it live with AI.

  1. When would you choose a hash map over a sorted array or balanced tree for storing key-value data, and what do you give up?

    Foundational
    How to answer

    What they’re really asking

    Whether you understand the practical time/space trade-offs of common data structures rather than just memorizing Big-O tables.

    Strong answer structure

    Hash map gives average O(1) insert/lookup/delete, ideal when you need fast point lookups by key and don't care about order. You give up ordered iteration and range queries (a tree gives O(log n) ordered operations), worst-case can degrade to O(n) on bad hashing/collisions, and you pay memory overhead and rehashing cost on growth. Choose a tree/sorted structure when you need sorted traversal, range scans, or predictable worst-case bounds.

    Likely follow-ups

    • How does a hash map resize, and why is amortized O(1) still true despite occasional O(n) rehashes?
    • What makes a good hash function, and what happens with a poor one?
    • How would you implement an LRU cache using these structures?
  2. Explain the difference between an array and a linked list. Give a concrete scenario where each is clearly the better choice.

    Foundational
    How to answer

    What they’re really asking

    Foundational grasp of contiguous vs. node-based memory and how access patterns drive the choice.

    Strong answer structure

    Arrays store elements contiguously: O(1) random access by index and great cache locality, but O(n) inserts/deletes in the middle and costly resizing. Linked lists store nodes with pointers: O(1) insert/delete given a node reference, but O(n) access and poor cache behavior. Use an array when you index frequently or iterate (e.g., a lookup table). Use a linked list when you splice items in/out of the middle often and rarely random-access (e.g., an LRU eviction list combined with a hash map).

    Likely follow-ups

    • Why do arrays usually outperform linked lists in practice even when Big-O favors the list?
    • How would you detect a cycle in a linked list?
  3. You have a function that's correct but too slow on large inputs. Walk me through how you'd diagnose and improve its performance.

    Intermediate
    How to answer

    What they’re really asking

    A disciplined, measurement-first optimization mindset rather than guess-and-tweak.

    Strong answer structure

    Reproduce with a representative large input and measure first: profile to find the actual hot path instead of guessing. Identify whether the cost is algorithmic (bad complexity), I/O bound, or due to constant factors. Attack the biggest contributor first: improve the algorithm/data structure (e.g., O(n^2) to O(n log n)), reduce redundant work (caching/memoization), or batch I/O. Re-measure after each change to confirm impact and avoid premature micro-optimizations. Validate correctness with tests throughout and stop when it meets the requirement.

    Likely follow-ups

    • How do you tell the difference between a CPU-bound and I/O-bound bottleneck?
    • When is it acceptable to ship the slower version?
  4. What is the difference between O(n log n) and O(n^2), and why does it matter once n gets large?

    Foundational
    How to answer

    What they’re really asking

    Whether you can reason about asymptotic growth and connect it to real-world input sizes.

    Strong answer structure

    Big-O describes how runtime grows with input size. O(n^2) work grows quadratically, so doubling n quadruples the work; O(n log n) grows only slightly faster than linear. At n=1,000 that's ~1,000,000 vs ~10,000 operations; at n=1,000,000 the gap becomes catastrophic (10^12 vs ~2x10^7). This is why efficient sorts (merge/quick) are O(n log n) while naive bubble/selection sort is O(n^2) and unusable at scale. The constant factors matter for small n, but asymptotics dominate as n grows.

    Likely follow-ups

    • Can an O(n^2) algorithm ever be the right choice over O(n log n)?
    • What's the difference between best, average, and worst case complexity?
  5. Design a URL shortener like bit.ly. Walk me through the core components and the main design decisions.

    Advanced
    How to answer

    What they’re really asking

    Systems design fundamentals: API design, data modeling, ID generation, read-heavy scaling, and caching trade-offs.

    Strong answer structure

    Clarify scale and read/write ratio (very read-heavy). Core API: POST a long URL returns a short code, GET the short code redirects. Generate the short code via a base62 encoding of an auto-increment/counter or a hash, handling collisions; store the mapping in a key-value or relational store keyed by short code. Since reads dominate, put a cache (e.g., in-memory/Redis) in front for hot links and use a CDN/redirect at the edge. Discuss custom aliases, expiration, analytics counters, and horizontal scaling via partitioning the key space. Mention 301 vs 302 redirect trade-offs for caching and analytics.

    Likely follow-ups

    • How do you guarantee unique short codes across multiple servers?
    • How would you handle 100x read traffic spikes on a viral link?
    • Where would you store click analytics without slowing redirects?
  6. What does it mean to design a system to scale horizontally vs vertically, and what new problems does horizontal scaling introduce?

    Intermediate
    How to answer

    What they’re really asking

    Understanding of scaling strategies and the distributed-systems complexity that comes with scaling out.

    Strong answer structure

    Vertical scaling means a bigger machine (more CPU/RAM); simple but capped by hardware limits and a single point of failure. Horizontal scaling means adding more machines behind a load balancer; nearly unbounded but introduces coordination problems: keeping servers stateless or sharing state, data partitioning/sharding, consistency across replicas, and handling partial failures. You typically push state to a shared data tier, make app servers stateless, and add caching and load balancing. Trade-off is operational complexity and consistency challenges in exchange for resilience and capacity.

    Likely follow-ups

    • How do you keep a web tier stateless when you need user sessions?
    • What is a load balancer doing, and what algorithms can it use?
  7. Explain the difference between a process and a thread, and why race conditions happen with threads.

    Intermediate
    How to answer

    What they’re really asking

    Core concurrency understanding: memory isolation vs shared memory and the root cause of concurrency bugs.

    Strong answer structure

    A process has its own isolated memory space; threads live inside a process and share its memory (heap, globals) while having separate stacks. Sharing memory makes threads cheap to communicate but dangerous: a race condition occurs when two threads access shared mutable state concurrently and at least one writes, so the result depends on unpredictable scheduling/interleaving. Classic example is two threads doing read-modify-write on the same counter losing updates. You fix it by synchronizing access (locks/mutexes), using atomic operations, or avoiding shared mutable state altogether (immutability, message passing).

    Likely follow-ups

    • What is a deadlock and how do you prevent one?
    • What's the difference between a mutex and a semaphore?
    • Why can't you always just 'add more locks' to fix concurrency bugs?
  8. What is a deadlock? Give the conditions required for one and a strategy to avoid it.

    Intermediate
    How to answer

    What they’re really asking

    Whether you understand lock ordering and the classic Coffman conditions behind deadlocks.

    Strong answer structure

    A deadlock is when two or more threads each hold a resource the other needs and none can proceed. It requires four conditions simultaneously: mutual exclusion, hold-and-wait, no preemption, and circular wait. The most common practical prevention is to break circular wait by acquiring locks in a consistent global order everywhere. Other strategies: use lock timeouts/try-lock and back off, reduce lock scope, use a single coarse lock, or avoid locks via lock-free structures. Mention you can detect deadlocks at runtime with a wait-for graph in some systems.

    Likely follow-ups

    • How does consistent lock ordering actually break the cycle?
    • What's livelock and how does it differ from deadlock?
  9. Describe a bug that was hard to track down. How did you isolate the root cause?

    Intermediate
    How to answer

    What they’re really asking

    Your debugging methodology under pressure and whether you fix root causes vs symptoms.

    Strong answer structure

    Use STAR. Situation: a specific intermittent or production bug (e.g., occasional data corruption or a flaky failure). Task: you owned finding and fixing it without a clear repro. Action: describe systematically narrowing it down: reproduce reliably, add logging/observability, bisect (git bisect or binary-search the code path), form and test hypotheses one at a time, and isolate the minimal failing case. Result: identified the true root cause (e.g., a race condition or off-by-one), fixed it, added a regression test, and shared the learning so it didn't recur. Emphasize discipline over guessing.

    Likely follow-ups

    • How did you confirm you fixed the real cause and not just a symptom?
    • What did you change in your process afterward to catch similar bugs earlier?
  10. How do you approach debugging an issue that only reproduces in production and not locally?

    Intermediate
    How to answer

    What they’re really asking

    Practical debugging skills when you can't simply attach a debugger, and respect for production safety.

    Strong answer structure

    Start by identifying what's different between prod and local: data volume, concurrency, configuration, environment, real traffic patterns, or timing. Lean on observability: structured logs, metrics, distributed traces, and error aggregation to narrow the failing request path. Try to reproduce by replicating the differing condition (real data shape, load, race timing) in a safe environment. Add targeted, low-risk instrumentation/feature flags rather than guessing. Form hypotheses and confirm with evidence before changing code. Throughout, avoid risky live experiments and add a regression test once found.

    Likely follow-ups

    • What would you log to diagnose an intermittent timeout?
    • How do you debug something that only happens under high concurrency?
  11. Explain what git rebase does and how it differs from git merge. When would you prefer each?

    Intermediate
    How to answer

    What they’re really asking

    Real working knowledge of version control history, not just memorized commands.

    Strong answer structure

    Merge combines two branches with a merge commit, preserving the actual branching history; it's non-destructive and shows when work diverged and joined. Rebase replays your commits on top of another branch's tip, producing a linear history as if you'd branched from the latest base; it rewrites commit hashes. Prefer rebase to keep a clean, linear feature-branch history before merging, or to tidy local commits. Prefer merge for integrating shared/long-lived branches. The golden rule: never rebase commits that others have already pulled, because rewriting shared history breaks their branches.

    Likely follow-ups

    • Why is rebasing a shared/public branch dangerous?
    • What does an interactive rebase let you do, and when is squashing useful?
    • How do you recover if a rebase goes wrong?
  12. Two developers edited the same file and you got a merge conflict. Walk me through how you resolve it correctly.

    Foundational
    How to answer

    What they’re really asking

    Comfort with everyday collaborative Git workflows and care about not silently dropping changes.

    Strong answer structure

    Git marks the conflicting regions with conflict markers showing both sides. Open the file, understand the intent of both changes (not just text), and combine them so the result is correct rather than blindly keeping one side. Run the build and tests to verify the merged code actually works. Mark the file resolved (git add) and complete the merge/rebase. If unsure of intent, talk to the other author. Emphasize that conflict resolution is a reasoning task about behavior, not just choosing 'mine' or 'theirs'.

    Likely follow-ups

    • How can you reduce how often conflicts happen in the first place?
    • What's the difference between resolving conflicts during a merge vs a rebase?
  13. What makes a good unit test, and how is it different from an integration test?

    Foundational
    How to answer

    What they’re really asking

    Testing fundamentals and where each test type belongs in the pyramid.

    Strong answer structure

    A good unit test is fast, isolated, deterministic, and tests one behavior of one unit with clear arrange-act-assert structure; it fails for one reason and the failure tells you what broke. It mocks/stubs external dependencies so only the unit's logic is exercised. An integration test verifies that multiple components work together (e.g., service plus real database), catching wiring and contract issues unit tests can't. The test pyramid argues for many fast unit tests, fewer integration tests, and even fewer slow end-to-end tests. Tests should assert behavior, not implementation details.

    Likely follow-ups

    • When should you mock a dependency vs use the real thing?
    • What's a flaky test and why is it dangerous to tolerate?
  14. What is test-driven development, and what do you see as its benefits and costs?

    Intermediate
    How to answer

    What they’re really asking

    Whether you have a thoughtful, non-dogmatic view of TDD and design-by-testing.

    Strong answer structure

    TDD is the red-green-refactor loop: write a failing test that specifies desired behavior, write the minimum code to pass it, then refactor with the test as a safety net. Benefits: it forces you to define requirements and interfaces before implementing, produces a regression suite, encourages testable (loosely coupled) design, and gives fast feedback. Costs: slower upfront, can over-test trivial code or lock in bad designs if you write tests around the wrong abstraction, and it's awkward for exploratory or UI-heavy work. A balanced answer says TDD is a valuable tool used where it fits, not a religion.

    Likely follow-ups

    • Have you used TDD on real work? Where did it help or hurt?
    • How do you avoid tests that just mirror the implementation?
  15. Explain the four pillars of object-oriented programming with a practical example of each.

    Foundational
    How to answer

    What they’re really asking

    Solid grasp of OOP fundamentals and ability to connect concepts to real code, not just definitions.

    Strong answer structure

    Encapsulation: bundle data with the methods that operate on it and hide internal state behind an interface (e.g., a BankAccount that validates withdrawals internally). Abstraction: expose what an object does, not how (a PaymentProcessor interface hiding gateway details). Inheritance: derive a class from a base to reuse/extend behavior (a SavingsAccount extending Account), used sparingly. Polymorphism: treat different types through a common interface so the right method runs at runtime (a list of Shapes all responding to area()). Good answers note that composition is often preferable to inheritance.

    Likely follow-ups

    • Why is 'composition over inheritance' often recommended?
    • Give an example where inheritance led to a fragile design.
  16. What does the SOLID 'S' (Single Responsibility Principle) mean, and why does violating it cause problems?

    Intermediate
    How to answer

    What they’re really asking

    Whether you can reason about cohesion and maintainability, not just recite the acronym.

    Strong answer structure

    Single Responsibility means a class/module should have one reason to change, i.e., one cohesive responsibility. Violating it creates 'god classes' that mix concerns (e.g., a class that parses input, applies business rules, and writes to the database). That coupling makes changes risky because editing one concern can break unrelated behavior, makes the code hard to test in isolation, and causes merge conflicts as many people touch the same file. Splitting responsibilities yields smaller, independently testable, reusable units. Tie it to real maintainability rather than treating SOLID as dogma.

    Likely follow-ups

    • Can you over-apply SRP and end up with too many tiny classes?
    • Briefly, what do the other SOLID principles address?
  17. When would you use composition instead of inheritance? Give a concrete example.

    Intermediate
    How to answer

    What they’re really asking

    Design judgment about modeling relationships and avoiding rigid class hierarchies.

    Strong answer structure

    Use inheritance only for a true 'is-a' relationship with shared substitutable behavior; use composition ('has-a') when you want to reuse or combine behaviors flexibly. Example: instead of a deep hierarchy of FlyingDuck, RubberDuck, etc., give a Duck a FlyBehavior and a QuackBehavior it delegates to (strategy pattern). Composition avoids the fragile base class problem, lets you swap behavior at runtime, and prevents combinatorial subclass explosion. Inheritance tightly couples subclass to superclass internals, so favor composition when behaviors vary independently or you'd otherwise force an awkward 'is-a'.

    Likely follow-ups

    • What is the fragile base class problem?
    • How does this relate to the Liskov Substitution Principle?
  18. What's the difference between synchronous and asynchronous execution, and when would you reach for async?

    Intermediate
    How to answer

    What they’re really asking

    Understanding of blocking vs non-blocking work and the right use cases for concurrency without threads.

    Strong answer structure

    Synchronous code runs step by step, blocking until each operation finishes. Asynchronous code lets a task start an operation (especially I/O) and continue other work, handling the result later via callbacks/promises/async-await, without blocking the thread. Async shines for I/O-bound workloads (network calls, disk, DB) where you'd otherwise waste time waiting, letting one thread juggle many in-flight operations. It does not speed up CPU-bound work, where you want real parallelism (threads/processes). Mention pitfalls: harder control flow, error handling, and reasoning about ordering.

    Likely follow-ups

    • Why doesn't async help with CPU-bound work?
    • What's the difference between concurrency and parallelism?
  19. Explain the concept of a deadlock-free vs thread-safe data structure. What does 'thread-safe' actually guarantee?

    Advanced
    How to answer

    What they’re really asking

    Deeper concurrency understanding and precision about what safety guarantees do and don't cover.

    Strong answer structure

    Thread-safe means concurrent access from multiple threads won't corrupt internal state or produce undefined behavior; each operation is correctly synchronized (via locks, atomics, or immutability). It does NOT guarantee that a sequence of separate operations is atomic together (e.g., check-then-act across two calls can still race), nor does it guarantee progress or freedom from deadlock. Deadlock-freedom is a separate property about lock acquisition order/protocol. A strong answer distinguishes individual-operation atomicity from compound-operation atomicity and notes that callers often still need external synchronization for invariants spanning multiple calls.

    Likely follow-ups

    • Why can a thread-safe map still have a race in 'if absent, put'?
    • What does a compare-and-swap operation give you?
  20. How would you design the data model for a feature where users can follow each other and see a feed of posts? Focus on the schema and read path.

    Advanced
    How to answer

    What they’re really asking

    Data modeling, relationship handling, and the fan-out-on-read vs fan-out-on-write trade-off.

    Strong answer structure

    Model users, posts (author_id, content, created_at), and a follows table (follower_id, followee_id) representing a many-to-many graph. The feed read path has two strategies: fan-out-on-read (query posts from everyone a user follows at read time, ordered by time) is simple and storage-light but slow for users following many accounts; fan-out-on-write (precompute each user's feed by pushing new posts into follower feed lists/caches) makes reads fast but writes expensive and is bad for celebrity accounts. A real system uses a hybrid: precompute for most, query-on-read for high-fanout authors. Add indexing on follower_id and created_at, and caching.

    Likely follow-ups

    • How do you handle a celebrity with 10 million followers?
    • Where do indexes matter most in this schema?
    • How would you paginate the feed efficiently?
  21. What is a stack and a queue, and give a real problem where each is the natural fit?

    Foundational
    How to answer

    What they’re really asking

    Basic but essential understanding of LIFO/FIFO structures and recognizing where they apply.

    Strong answer structure

    A stack is LIFO: push/pop from one end, O(1). Natural fits: function call stacks, undo functionality, matching brackets, and depth-first traversal. A queue is FIFO: enqueue at one end, dequeue at the other, O(1). Natural fits: task/job scheduling, buffering, breadth-first traversal, and producer-consumer pipelines. A strong answer ties the structure to the ordering guarantee the problem needs (most-recent-first vs oldest-first) and mentions variants like deques and priority queues.

    Likely follow-ups

    • How would you implement a queue using two stacks?
    • When would you use a priority queue instead of a plain queue?
  22. Explain the difference between SQL and NoSQL databases and how you'd decide which to use for a new service.

    Intermediate
    How to answer

    What they’re really asking

    Whether you can pick storage based on data shape and access patterns rather than hype.

    Strong answer structure

    SQL/relational databases enforce a schema, support joins and ACID transactions, and excel when data is structured, relationships matter, and you need strong consistency. NoSQL covers document, key-value, wide-column, and graph stores; they trade rigid schemas and joins for flexibility, horizontal scalability, and high write/read throughput, often with eventual consistency. Decide based on access patterns: relational with complex queries and transactional integrity points to SQL; massive scale, flexible/evolving schema, or simple key-based access points to NoSQL. Note many systems use both (polyglot persistence) and that 'NoSQL' is not one thing.

    Likely follow-ups

    • What does ACID mean, and what does eventual consistency give up?
    • When would a document store be a poor choice?
  23. Tell me about a time you disagreed with a technical decision on your team. How did you handle it?

    Intermediate
    How to answer

    What they’re really asking

    Collaboration, communication, and whether you can disagree constructively and commit.

    Strong answer structure

    Use STAR. Situation: a real decision you had concerns about (e.g., a chosen technology or architecture). Task: you wanted the best outcome while respecting the team. Action: you raised concerns with evidence and trade-offs rather than opinion, listened to others' reasoning, perhaps prototyped or gathered data, and framed it around shared goals. Result: either you persuaded the team with data, or you understood their reasoning and committed to the decision, supporting it fully. Emphasize 'disagree and commit', focusing on outcomes over ego.

    Likely follow-ups

    • What if you'd been overruled and the decision later caused problems?
    • How do you raise concerns without seeming obstructive?
  24. What is recursion, and what must every recursive solution have to avoid running forever or blowing the stack?

    Foundational
    How to answer

    What they’re really asking

    Fundamental understanding of recursion, base cases, and the call-stack cost.

    Strong answer structure

    Recursion is a function calling itself on a smaller subproblem until reaching a base case. Every recursive solution needs (1) one or more base cases that terminate without recursing, and (2) a recursive step that makes progress toward a base case. Without a correct base case or progress, it recurses infinitely and overflows the stack, since each call consumes a stack frame. Deep recursion risks stack overflow even when logically correct, so for large depths you may convert to iteration or use tail-call/explicit-stack approaches. Mention memoization to avoid recomputing overlapping subproblems.

    Likely follow-ups

    • When would you rewrite a recursive function iteratively?
    • How does memoization change the complexity of recursive Fibonacci?
  25. What is a REST API, and what makes an API design 'RESTful'? Where do people commonly get it wrong?

    Intermediate
    How to answer

    What they’re really asking

    Practical API design knowledge and ability to critique common anti-patterns.

    Strong answer structure

    REST is an architectural style: resources identified by URLs, manipulated with standard HTTP verbs (GET read, POST create, PUT/PATCH update, DELETE remove), stateless requests, and meaningful status codes. RESTful design uses nouns for resources (not verbs in the path), correct verb semantics, idempotency where expected (GET/PUT/DELETE), and consistent, versioned, well-documented contracts. Common mistakes: putting actions in URLs like /getUser or /createOrder, using POST for everything, returning 200 for errors, ignoring proper status codes, and chatty or inconsistent endpoints. Mention idempotency and pagination as real-world concerns.

    Likely follow-ups

    • Which HTTP methods should be idempotent and why does it matter?
    • How would you version an API without breaking existing clients?
  26. Describe a time you had to deliver under a tight deadline. What did you trade off and how did you decide?

    Intermediate
    How to answer

    What they’re really asking

    Prioritization, pragmatism, and how you manage scope and technical debt under pressure.

    Strong answer structure

    Use STAR. Situation: a real time-boxed deliverable. Task: ship something valuable on time without wrecking quality. Action: you scoped ruthlessly to the must-haves, communicated trade-offs to stakeholders, took deliberate (not accidental) shortcuts, and documented the debt to revisit. You protected the things that are expensive to fix later (data integrity, security) while deferring nice-to-haves. Result: delivered on time, were transparent about what was cut, and followed up to pay down the debt. Emphasize conscious decision-making and communication over heroics.

    Likely follow-ups

    • How do you distinguish acceptable shortcuts from dangerous ones?
    • How did you make sure the deferred work actually got done?
  27. Explain what caching is, the main invalidation strategies, and why cache invalidation is considered hard.

    Advanced
    How to answer

    What they’re really asking

    Understanding of caching trade-offs and the consistency problems it introduces.

    Strong answer structure

    Caching stores a copy of expensive-to-compute or slow-to-fetch data closer to the consumer to reduce latency and load. Strategies include time-to-live expiration, write-through (write to cache and store together), write-back, and explicit invalidation on update. It's hard because the cache can serve stale data: you must decide when entries are no longer valid, handle distributed caches where multiple nodes hold copies, avoid thundering-herd on expiry, and balance freshness against hit rate. Trade-off is consistency vs performance. Mention cache stampede mitigation and that eviction policy (LRU/LFU) matters under memory limits.

    Likely follow-ups

    • What is a cache stampede and how do you prevent it?
    • How do you keep multiple cache nodes consistent after a write?
  28. What is the difference between an interface and an abstract class, and when would you choose one over the other?

    Intermediate
    How to answer

    What they’re really asking

    OOP design judgment around contracts vs shared implementation.

    Strong answer structure

    An interface defines a pure contract (a set of methods a type must implement) with no or minimal implementation, and a class can implement many interfaces. An abstract class can provide shared state and default implementations but can't be instantiated, and a class typically extends only one. Choose an interface to define a capability multiple unrelated types can fulfill (e.g., Comparable, Serializable) and to enable polymorphism without forcing a hierarchy. Choose an abstract class when subclasses share real implementation/state and have a true 'is-a' relationship. Modern languages blur this with default interface methods, so explain the trade-off rather than a hard rule.

    Likely follow-ups

    • Why does single vs multiple inheritance affect this choice?
    • How do default/interface methods change the trade-off?
  29. Given a list of integers, how would you find whether any two of them sum to a target value? Discuss approaches and their trade-offs.

    Foundational
    How to answer

    What they’re really asking

    Whether you can reason about a time/space trade-off and reach for the right data structure, not memorize a LeetCode answer.

    Strong answer structure

    Brute force checks every pair: O(n^2) time, O(1) space; fine for tiny inputs. Better: iterate once and keep a hash set of values seen so far; for each value check if target minus value is already in the set, giving O(n) time at the cost of O(n) space. If the list is already sorted, a two-pointer approach from both ends finds it in O(n) time with O(1) extra space. The point is articulating the trade-off: hash set buys speed with memory; two pointers needs sorted input. State assumptions about duplicates and whether indices or values are needed.

    Likely follow-ups

    • How does your approach change if the array is sorted?
    • What if you needed all pairs that sum to the target, not just one?
    • How would you extend this to three numbers summing to a target?
  30. What does a code review do for a team, and what do you actually look for when reviewing someone's pull request?

    Foundational
    How to answer

    What they’re really asking

    Engineering maturity, collaboration, and quality standards beyond just writing code.

    Strong answer structure

    Code review catches bugs early, spreads knowledge, keeps the codebase consistent, and mentors teammates. When reviewing, check correctness and edge cases first, then readability and clarity, test coverage, adherence to conventions, security and performance concerns, and whether the change matches its stated intent and scope. Give specific, kind, actionable feedback, distinguish blocking issues from nits, and praise good work. Avoid bikeshedding and personal attacks; assume good intent and ask questions rather than dictate. Emphasize that the goal is a better product and a stronger team, not gatekeeping.

    Likely follow-ups

    • How do you give critical feedback without discouraging the author?
    • What would make you block a PR versus approve with comments?