Software Engineer
Updated for 2026: Software Engineer interview questions and answers covering core skills, tools, and best practices for roles in the US, Europe & Canada.
What is the difference between REST and GraphQL?
REST (Representational State Transfer) and GraphQL are two different approaches to API design. **REST:** - **Architecture:** Resource-based endpoints (e.g., `/users/:id`). - **Data fetching:** Multiple endpoints can cause over/under-fetching. - **Caching:** Works well with HTTP caching. - **Versioning:** Often via URL or headers. **GraphQL:** - **Architecture:** Query language + runtime with a typed schema. - **Data fetching:** Client asks for exactly what it needs (often one endpoint). - **Versioning:** Typically schema evolution (add fields) instead of `/v2`. - **Caching:** Possible, but often needs client/server strategy. **Key takeaway:** REST is great for simple, cache-friendly APIs; GraphQL shines when clients need flexible, efficient data access across many related resources.
Explain Big O notation with examples.
Big O notation describes how an algorithm’s time or space grows as input size (n) grows. **Common time complexities:** - **O(1):** Constant time (array index lookup) - **O(log n):** Logarithmic (binary search) - **O(n):** Linear (single loop) - **O(n log n):** Efficient sorting (merge sort) - **O(n^2):** Nested loops (bubble sort) **Interview tip:** Always mention worst-case vs average-case, and include space complexity when relevant. Big O helps compare scalability before optimizing micro-details.
How would you design a URL shortening service like Bitly?
A good URL shortener design covers requirements, data model, and scaling. **Requirements:** create short links, redirect quickly, analytics (optional), high availability. **Key design choices:** - **ID generation:** Base62 encode a unique ID (Snowflake/sequence) to avoid collisions. - **Storage:** Key-value mapping `shortKey -> longUrl` (plus createdAt, expiry, owner). - **Caching:** Cache popular keys in Redis to reduce DB reads. - **Redirects:** Use 301 (permanent) or 302 (temporary) depending on needs. - **Scale:** Partition by `shortKey`, add read replicas, and front with CDN for edge redirects. **Risk areas:** abuse/spam, link expiration, and analytics write amplification.
What are the SOLID principles in software engineering?
SOLID is five OO design principles that improve maintainability: - **S (SRP):** One reason to change. - **O (OCP):** Open for extension, closed for modification. - **L (LSP):** Subtypes must be substitutable for base types. - **I (ISP):** Many small interfaces, not one giant interface. - **D (DIP):** Depend on abstractions, not concretions. **Interview tip:** Give a practical example (e.g., swapping a payment provider using an interface) to show you can apply SOLID, not just recite it.
How does a hash map (hash table) work internally?
A hash map stores key-value pairs using a hash function to map keys to bucket indices. **Core ideas:** - Compute `hash(key)` then `index = hash % capacity`. - Store entries in a bucket. **Collisions:** multiple keys can map to the same bucket. - **Chaining:** bucket holds a list/tree of entries. - **Open addressing:** probe for the next free slot (linear/quadratic probing). **Resizing:** When load factor is high, rehash into a bigger table. **Complexity:** Average O(1) for get/put; worst-case can degrade to O(n) if collisions are extreme or hash is poor.
TCP vs UDP: what’s the difference and when would you use each?
**TCP** is connection-oriented and reliable (ordered delivery, retransmissions, flow control). **UDP** is connectionless and best-effort (no ordering or delivery guarantee). **Use TCP for:** HTTP/HTTPS, file transfers, email—when correctness matters. **Use UDP for:** VoIP, gaming, streaming—when latency matters more than perfect delivery. **Interview tip:** Mention that modern protocols like QUIC run on UDP while adding reliability at the application/protocol layer.
What are ACID properties in databases?
ACID ensures reliable transactions: - **Atomicity:** all-or-nothing. - **Consistency:** constraints/invariants remain valid. - **Isolation:** concurrent transactions don’t interfere (depends on isolation level). - **Durability:** committed data survives crashes. **Interview tip:** Connect ACID to real problems like double-charging in payments, and mention trade-offs like performance vs stronger isolation.
What is the SDLC (Software Development Life Cycle)?
SDLC is the process of building software from idea to production and beyond. **Typical phases:** 1) Requirements & planning 2) Design (architecture, UX) 3) Implementation 4) Testing (unit/integration/e2e) 5) Deployment 6) Maintenance & iteration Teams implement SDLC differently (Waterfall vs Agile/DevOps), but the goals are the same: reduce risk, ship reliably, and improve over time.
How do you resolve Git merge conflicts?
A merge conflict happens when Git can’t automatically combine changes. **Steps:** 1) Run `git status` to see conflicted files. 2) Open the file and find conflict markers `<<<<<<<`, `=======`, `>>>>>>>`. 3) Decide the correct final code (choose one side or combine). 4) Remove markers, run tests. 5) `git add` and complete the merge (`git commit` or continue rebase). **Prevent conflicts:** smaller PRs, frequent pulls, clear ownership, and avoiding long-lived branches.
What is Dependency Injection (DI) and why is it useful?
Dependency Injection provides a class’s dependencies from the outside instead of creating them inside the class. **Why it matters:** - Improves **testability** (swap real dependencies for mocks). - Reduces **coupling** (depend on interfaces/abstractions). - Improves **maintainability** and configuration. **Common forms:** constructor injection (preferred), setter injection, and framework-based IoC containers. **Interview tip:** Mention DI + DIP (from SOLID) together, and give an example like injecting a `PaymentGateway` interface.
What is the difference between a process and a thread?
A **process** is an independent program instance with its own memory space. A **thread** is a lightweight execution unit within a process that shares memory with other threads. **Processes:** better isolation; IPC needed for communication. **Threads:** cheaper context switching; need synchronization to avoid race conditions. **Interview tip:** Mention that multi-threading can boost throughput but introduces complexity (locks, deadlocks, contention).
How do you optimize a slow database query?
A reliable approach is: 1) Use **EXPLAIN/EXPLAIN ANALYZE** to see the plan. 2) Add or fix **indexes** on WHERE/JOIN/ORDER BY columns. 3) Avoid `SELECT *` and reduce returned rows. 4) Rewrite expensive joins/subqueries; watch N+1 ORM issues. 5) Use pagination and avoid large offsets. 6) Cache hot reads (Redis) when appropriate. 7) Check database config and statistics. **Interview tip:** Explain trade-offs: more indexes speed reads but slow writes and increase storage.
What is CI/CD and why is it important?
CI/CD automates building, testing, and releasing software. - **CI (Continuous Integration):** merge small changes frequently and run automated tests. - **CD (Continuous Delivery/Deployment):** automatically prepare releases (delivery) or deploy to production (deployment). **Why it matters:** faster feedback, fewer regressions, predictable releases, and safer deployments.
Explain the CAP theorem in distributed systems.
CAP says a distributed system can guarantee at most two of: - **Consistency (C):** every read sees the latest write. - **Availability (A):** every request gets a non-error response. - **Partition tolerance (P):** the system works even when nodes can’t communicate. Because partitions happen in real systems, you usually choose **CP** or **AP** behavior during failures. **Interview tip:** Give examples: CP-like systems favor correctness; AP-like systems favor uptime with eventual consistency.
How do you answer: “Tell me about a conflict with a coworker”?
Use the **STAR** method and keep it professional. - **Situation/Task:** explain context and goal. - **Action:** show listening, clarity, and collaboration. - **Result:** measurable outcome (delivered on time, fewer bugs, improved relationship). **What interviewers want:** emotional maturity, communication, and problem-solving—not drama.
What’s the difference between unit, integration, and end-to-end (E2E) tests?
**Unit tests** validate small units (functions/classes) in isolation. **Integration tests** validate interactions between components (e.g., service + DB). **E2E tests** validate full user flows through the system (UI → API → DB). **Best practice:** follow the testing pyramid—many fast unit tests, fewer integration tests, and a small number of E2E tests for critical paths.
How do you write effective unit tests?
Good unit tests are fast, deterministic, and focused. **Checklist:** - Use **Arrange–Act–Assert**. - Test behavior, not implementation details. - Prefer real objects; mock only external boundaries (I/O, network). - Cover edge cases and failure paths. - Use meaningful test names. **Bonus:** aim for readable tests that act as documentation for expected behavior.
What are common caching strategies and how do you handle cache invalidation?
Common caching patterns: - **Cache-aside:** app reads from cache, falls back to DB, then populates cache. - **Read-through:** cache layer loads from DB on miss. - **Write-through / write-behind:** writes go through cache (sync/async) before DB. **Invalidation options:** - TTL/expiration - explicit deletes on writes - versioned keys (e.g., `user:v3:123`) **Interview tip:** explain trade-offs between freshness, complexity, and performance.
Message queue vs event stream: what’s the difference?
A **message queue** focuses on work distribution: messages are consumed and removed (e.g., task processing). An **event stream** focuses on immutable logs: events are appended and consumers track offsets (e.g., analytics, change data capture). **Typical mapping:** - Queues: RabbitMQ/SQS (work queues) - Streams: Kafka/Kinesis (event logs) Choose based on delivery semantics, ordering, retention, and consumer model.
What are common API rate limiting algorithms?
Popular rate limiting techniques: - **Fixed window:** simple but can burst at window edges. - **Sliding window:** smoother enforcement. - **Token bucket:** allows bursts up to bucket size; refills over time. - **Leaky bucket:** steady outflow; good for smoothing. **Implementation notes:** distributed rate limiting often uses Redis (atomic increments, Lua scripts) or gateway-level controls.
OAuth 2.0 vs JWT: what’s the difference?
**OAuth 2.0** is an authorization framework (how clients get access). **JWT** is a token format (how a token is represented). You can use OAuth 2.0 with JWT access tokens, but OAuth tokens can also be opaque. **Interview tip:** mention access tokens vs refresh tokens, scopes, and that OpenID Connect adds authentication on top of OAuth 2.0.
How should passwords be stored securely?
Never store plaintext passwords. **Best practice:** - Use a slow, adaptive hash like **Argon2id** (or bcrypt/scrypt). - Use a unique **salt** per password (usually built into libs). - Consider a **pepper** stored separately (optional). - Enforce MFA and rate limits on login. Also store only what you need and log auth events safely (no sensitive data).
Database normalization vs denormalization: when do you choose each?
**Normalization** reduces duplication and improves consistency (good for OLTP). It can increase join cost. **Denormalization** duplicates data to speed reads and simplify queries (common in analytics and read-heavy systems). It increases write complexity and risk of inconsistency. A practical approach: start normalized, then denormalize selectively using measurements (slow queries, hot endpoints).
What is eventual consistency and how do sagas help in distributed systems?
**Eventual consistency** means replicas/services converge to the same value over time, but reads may be stale temporarily. **Sagas** manage multi-step workflows across services without a global transaction: - Break a business transaction into steps. - Each step has a compensating action to undo work if later steps fail. This improves availability and scalability, at the cost of more complex failure handling.
What is a deadlock and how do you prevent it?
A **deadlock** occurs when multiple actors wait forever for each other’s resources. **Prevention strategies:** - Acquire locks in a consistent global order. - Use timeouts and retries. - Reduce lock scope/duration. - Prefer lock-free or immutable designs when possible. In databases, proper indexing and shorter transactions can also reduce deadlock risk.
How do you debug a memory leak in an application?
A memory leak is memory that’s no longer needed but still referenced. **Approach:** - Reproduce and measure (RSS/heap growth). - Capture heap snapshots / dumps. - Compare snapshots to find retained objects. - Identify unexpected references (caches, global lists, event listeners). - Fix and add regression tests/alerts. **Interview tip:** mention that caches need eviction (LRU/TTL) and listeners must be unsubscribed.
What is a race condition and how do you fix it?
A **race condition** happens when program correctness depends on timing between concurrent operations. **Fixes:** - Use locks/mutexes around shared state. - Use atomic operations or compare-and-swap. - Use message passing (queues/actors) instead of shared memory. - Prefer immutability. **Interview tip:** provide a simple example (counter increments) and show a safe solution.
When would you use the Strategy and Factory design patterns?
**Strategy**: choose behavior at runtime (e.g., different pricing algorithms). It reduces `if/else` chains and supports extension. **Factory**: centralize object creation (e.g., create different `PaymentProvider` implementations). It hides construction details and supports DI. In interviews, emphasize the goal: reduce coupling, improve extensibility, and keep code open for new behaviors without large rewrites.
What do you look for in a code review?
A strong code review checks more than style: - Correctness and edge cases - Readability and maintainability - Tests (coverage of new behavior) - Performance implications - Security concerns (input validation, auth checks) - API/UX impact - Observability (logs/metrics where needed) **Good practice:** be kind, specific, and propose actionable improvements.
What are feature flags and how do you roll out features safely?
Feature flags let you enable/disable functionality at runtime. **Why use them:** safer releases, gradual rollouts, quick rollback (kill switch), A/B tests. **Rollout strategies:** - percentage-based canary - user/segment targeting - environment-based flags **Pitfalls:** flag debt (old flags), inconsistent state, and security (don’t expose privileged flags to clients without server enforcement).