.NET Backend Developer Interview β€” Reviewed Study Guide

A comprehensive, prioritized reference for C#, ASP.NET Core, EF Core, SQL, HTTP, security, testing, operations, practical rounds, and system design.

Reviewed for the 2026 .NET landscape. Use it as the main study map, then prove the knowledge through coding, SQL, debugging, and mock interviews.

C# / CLRASP.NET Core EF Core / SQLHTTP / Security System DesignPractical Rounds

StartWhat Actually Matters in a .NET Backend Interview 10/100/0 βœ“

This guide is intentionally broad, but not every topic deserves equal study time. Use these tiers to avoid spending hours on advanced material before the fundamentals are solid.

Importance ratings: every section, subtopic, detailed bullet, comparison row, and interview question carries a 1–10 score for how much it matters in a typical .NET backend interview. 9–10 asked in almost every interview — master these first · 7–8 very common — expected at mid-level · 5–6 comes up regularly — senior or role-specific · 1–4 niche — skip until everything else is solid.

Must know β€” most interviews 10/10

  • 10/10C# types, collections, generics, LINQ, exceptions, equality, nullable references
  • 10/10Async/await, I/O vs CPU work, cancellation, concurrency basics
  • 10/10ASP.NET Core pipeline, DI lifetimes, configuration, validation, auth, error handling
  • 10/10EF Core querying, tracking, relationships, migrations, concurrency
  • 10/10SQL joins, indexes, transactions, isolation, query plans
  • 10/10HTTP/REST, status codes, security basics, unit and integration testing
  • 10/10Explaining one real project, debugging approach, and behavioral stories

Strong advantage β€” mid-level+ 8/10

  • 8/10Caching, queues, retries, idempotency, observability, health checks
  • 8/10Docker, CI/CD, cloud fundamentals, deployment and rollback
  • 9/10API versioning, pagination, OpenAPI, Problem Details
  • 8/10Performance diagnosis, N+1, projections, keyset pagination
  • 8/10Basic system design with explicit trade-offs and failure handling

Role-dependent β€” learn after core 5/10

  • 3/10Advanced dynamic programming, graph algorithms, bit manipulation
  • 5/10Kubernetes internals, sharding, consistent hashing
  • 5/10CQRS, event sourcing, sagas, YARP, deep microservices patterns
  • 4/10Span<T>, Native AOT, low-level GC tuning, newest syntax trivia

Current platform context: as of 2026, .NET 10 is the current LTS release and C# 14 is current. Know which version the employer uses, but prioritize durable runtime, web, data, and design fundamentals over memorizing release notes.

Company style matters: large product companies may emphasize algorithms and system design; typical enterprise .NET teams often emphasize APIs, EF Core, SQL, async code, testing, Azure, and debugging. Adjust practice to the job description.

1Data Structures & Algorithms Company-dependent 7/100/0 βœ“

This round is pattern-based. You are tested on whether you can choose a suitable data structure, explain trade-offs, write correct code, and reason about time and space. Arrays, dictionaries, strings, stacks/queues, trees, BFS/DFS, binary search, and common two-pointer/sliding-window problems are the highest-value topics. Deep dynamic programming, advanced graphs, and bit tricks are mainly important for algorithm-heavy companies.

1.1 Big-O β€” what it really means 9/10

Big-O describes how the number of operations (time) or amount of memory (space) grows as the input size n grows toward infinity. It ignores constants and hardware β€” it's about the shape of growth, not the exact count.

How to derive it in 4 steps:

  1. 9/10Count the loops. One loop over n = O(n). A loop inside a loop, both over n = O(nΒ²).
  2. 9/10Halving the input each step = O(log n) (that's binary search, balanced trees).
  3. 9/10Drop constants and lower-order terms: O(2n + 100) becomes O(n); O(nΒ² + n) becomes O(nΒ²) because nΒ² dominates as n grows.
  4. 9/10Recursion: multiply the number of calls by the work per call. Naive Fibonacci makes 2 calls per level for n levels = O(2ⁿ).
ComplexityNamen=10n=1,000Typical source
9/10O(1)Constant11Hash lookup, array index, arithmetic
9/10O(log n)Logarithmic~3~10Binary search, balanced BST
9/10O(n)Linear101,000One pass over data
9/10O(n log n)Linearithmic~33~10,000Good sorting, divide & conquer
9/10O(nΒ²)Quadratic1001,000,000Nested loops, all pairs
9/10O(2ⁿ)Exponential1,024astronomicalNaive recursion, subsets
9/10O(n!)Factorial3.6Mβ€”All permutations

A common optimization: if a problem repeatedly asks β€œhave I seen X?” or searches for complements, a HashSet/Dictionary can often reduce O(nΒ²) work to O(n) by trading memory for speed. It is not automatic: ordering, range queries, duplicates, and worst-case memory still matter.

Space complexity counts extra memory you allocate: a second array = O(n); recursion uses the call stack, so depth-d recursion = O(d) space even with no explicit arrays.

1.2 The core data structures β€” when & why 9/10

Study Card #1

Array / List O(1) access 9/10

Contiguous memory. Reading by index is O(1). Appending to a List<T> is amortized O(1) (it occasionally doubles its backing array). Inserting/removing in the middle is O(n) because everything shifts. Use when you need indexed access or you'll iterate in order.

Dictionary / HashSet O(1) lookup 10/10

Backed by a hash table: it hashes the key to a bucket. Average insert/lookup/delete is O(1); worst case O(n) if many keys collide. No ordering. Dictionary<K,V> maps keys to values; HashSet<T> just tracks membership. Use for counting, deduping, "seen before?", grouping, caching, adjacency lists.

Stack β€” LIFO push/pop O(1) 8/10

Last in, first out. Use for undo, expression/bracket matching, backtracking, and iterative DFS. The call stack itself is a stack β€” that's why recursion and DFS are interchangeable.

Queue β€” FIFO enqueue/dequeue O(1) 8/10

First in, first out. Use for BFS, scheduling, producer/consumer buffers. PriorityQueue<TElement,TPriority> (a heap) pops the smallest priority first β€” use it for Dijkstra and "top-K".

Linked List O(1) insert at node 6/10

Each node points to the next (and maybe previous). O(1) to insert/delete if you already hold the node, but O(n) to find something. Rare in real backend code, common in interviews (reverse a list, detect a cycle, merge two lists).

Tree / Binary Search Tree O(log n) balanced 7/10

Hierarchical parent→children. A BST keeps left < node < right, so search/insert/delete is O(log n) when balanced (degrades to O(n) if it becomes a straight line). Traversals: in-order gives sorted output, pre-order copies a tree, post-order deletes/evaluates, level-order is BFS.

Heap / Priority Queue peek O(1), push/pop O(log n) 6/10

A binary tree kept partially ordered so the min (or max) is always at the root. Use for "K largest/smallest/most frequent", merging sorted streams, Dijkstra, schedulers.

Graph V vertices, E edges 6/10

Nodes + edges; store as an adjacency list (Dictionary<int, List<int>>) for sparse graphs. BFS finds shortest paths in an unweighted graph; DFS explores deeply and backtracks; Dijkstra uses a priority queue to find shortest paths when edge weights are non-negative.

1.3 The patterns that solve most problems β€” with templates 8/10

When you read a problem, try to map it to one of these. The trigger phrases in italics tell you which to reach for.

Two Pointers sorted array, pair, palindrome 8/10

Two indices move toward each other (or one chases the other). Trigger: "sorted array", "pair that sums to target", "is it a palindrome", "remove duplicates in place".

// Pair that sums to target in a SORTED array β€” O(n), O(1) space
int lo = 0, hi = arr.Length - 1;
while (lo < hi) {
    int sum = arr[lo] + arr[hi];
    if (sum == target) return new[]{ lo, hi };
    if (sum < target) lo++;   // need bigger β†’ move left pointer up
    else hi--;                // need smaller β†’ move right pointer down
}

Sliding Window longest/shortest subarray or substring 8/10

Grow a window from the right, shrink from the left when a condition breaks. Turns many O(nΒ²) substring problems into O(n). Trigger: "longest/shortest contiguous …", "substring without repeats", "max sum of k elements".

// Longest substring with no repeating characters β€” O(n)
var last = new Dictionary<char,int>();
int start = 0, best = 0;
for (int end = 0; end < s.Length; end++) {
    if (last.TryGetValue(s[end], out int idx) && idx >= start)
        start = idx + 1;              // jump past the previous duplicate
    last[s[end]] = end;
    best = Math.Max(best, end - start + 1);
}
return best;

Fast & Slow Pointers cycle detection 6/10

A slow pointer moves 1 step, a fast pointer 2 steps. If there's a cycle they meet. Trigger: "does the linked list have a cycle", "find the middle".

Binary Search sorted, or 'search the answer' 9/10

Repeatedly halve the search space β€” O(log n). Also works on an abstract "answer space" (e.g. minimum capacity that satisfies a condition). Trigger: "sorted", "minimum/maximum value that works".

int lo = 0, hi = arr.Length - 1;
while (lo <= hi) {
    int mid = lo + (hi - lo) / 2;      // avoids integer overflow
    if (arr[mid] == target) return mid;
    if (arr[mid] < target) lo = mid + 1;
    else hi = mid - 1;
}
return -1;

BFS & DFS trees & graphs 8/10

BFS uses a queue and visits level by level β†’ shortest path in unweighted graphs. DFS uses recursion/stack and goes deep β†’ good for exploring all paths, detecting cycles, topological sort.

// BFS shortest path (unweighted) β€” O(V + E)
var q = new Queue<int>(); var dist = new Dictionary<int,int>{ [start]=0 };
q.Enqueue(start);
while (q.Count > 0) {
    int node = q.Dequeue();
    foreach (int next in graph[node])
        if (!dist.ContainsKey(next)) {
            dist[next] = dist[node] + 1;
            q.Enqueue(next);
        }
}

Backtracking permutations, combinations, subsets 5/10

Try a choice, recurse, then undo it and try the next. Explores a decision tree. Trigger: "all combinations/permutations/subsets", "sudoku", "generate all valid …".

void Backtrack(List<int> path, bool[] used) {
    if (path.Count == nums.Length) { results.Add(new(path)); return; }
    for (int i = 0; i < nums.Length; i++) {
        if (used[i]) continue;
        used[i] = true;  path.Add(nums[i]);      // choose
        Backtrack(path, used);                    // explore
        used[i] = false; path.RemoveAt(path.Count-1); // un-choose
    }
}

Other must-know patterns 6/10

  • 6/10Hash Map counting β€” frequencies, anagrams, "first unique". O(n).
  • 6/10Prefix Sum β€” precompute cumulative sums so any range sum is O(1).
  • 6/10Top-K / Heap β€” keep a heap of size K β†’ O(n log k).
  • 6/10Merge Intervals β€” sort by start, then merge overlaps.
  • 6/10Topological Sort β€” order tasks with dependencies (build order, course schedule); DFS or Kahn's algorithm.
  • 6/10Union-Find β€” group connected items, detect graph cycles, near-O(1) per op.
  • 6/10Greedy β€” take the locally best choice; works when local optima lead to a global optimum (interval scheduling, Huffman).

1.4 Sorting & searching you should be able to explain 6/10

AlgorithmAverageWorstSpaceStable?Notes
6/10Quick SortO(n log n)O(nΒ²)O(log n)NoFast in practice; bad pivot β†’ worst case
6/10Merge SortO(n log n)O(n log n)O(n)YesPredictable; used for linked lists & external sort
6/10Heap SortO(n log n)O(n log n)O(1)NoIn-place, no recursion
6/10Insertion SortO(nΒ²)O(nΒ²)O(1)YesGreat for tiny/nearly-sorted data

In real code you just call list.Sort() (introsort β€” a quicksort/heapsort hybrid) or OrderBy (stable). But interviewers ask you to explain why merge sort is O(n log n): it splits the array in half (log n levels) and does O(n) work merging at each level.

1.5 Recursion & Dynamic Programming (the scary part, demystified) 6/10

Recursion = a function calling itself on a smaller input until a base case stops it. Every recursion needs (1) a base case and (2) progress toward it.

Dynamic Programming = recursion where subproblems repeat, so you cache results to avoid recomputing. Two flavors:

  • 6/10Memoization (top-down): normal recursion + a cache (Dictionary/array).
  • 6/10Tabulation (bottom-up): fill a table from the smallest subproblem upward.

Classic example β€” Fibonacci goes from O(2ⁿ) to O(n):

// Naive: O(2^n) β€” recomputes the same values exponentially
int Fib(int n) => n < 2 ? n : Fib(n-1) + Fib(n-2);

// Memoized: O(n) β€” each value computed once
var memo = new Dictionary<int,long>();
long Fib(int n) {
    if (n < 2) return n;
    if (memo.TryGetValue(n, out var v)) return v;
    return memo[n] = Fib(n-1) + Fib(n-2);
}

How to spot a DP problem: you're asked for a count, a min/max, or "is it possible", AND the answer for n depends on answers for smaller inputs, AND those overlap. Classics: coin change, longest common subsequence, edit distance, knapsack, climbing stairs, house robber.

1.6 Fully worked problems (read these like flashcards) 7/10

7/10Two Sum β€” return indices of two numbers adding to target

Idea: as you scan, remember each value's index. For each number, check if its complement (target βˆ’ value) was already seen. One pass, O(n) time, O(n) space.

public int[] TwoSum(int[] nums, int target) {
    var seen = new Dictionary<int,int>();       // value -> index
    for (int i = 0; i < nums.Length; i++) {
        int need = target - nums[i];
        if (seen.TryGetValue(need, out int j)) return new[]{ j, i };
        seen[nums[i]] = i;
    }
    return Array.Empty<int>();
}
7/10Valid Parentheses β€” is a string of brackets balanced?

Idea: push opening brackets; on a closing bracket, the top of the stack must be its match. Stack empty at the end = valid. O(n).

public bool IsValid(string s) {
    var st = new Stack<char>();
    var pairs = new Dictionary<char,char>{ [')']='(', [']']='[', ['}']='{' };
    foreach (char c in s) {
        if (pairs.ContainsKey(c)) {
            if (st.Count == 0 || st.Pop() != pairs[c]) return false;
        } else st.Push(c);
    }
    return st.Count == 0;
}
7/10Number of Islands β€” count connected groups of '1' in a grid

Idea: scan the grid; each time you hit an unvisited '1', it's a new island β€” flood-fill (DFS/BFS) all connected land so you don't count it again. O(rows Γ— cols).

public int NumIslands(char[][] grid) {
    int count = 0;
    void Sink(int r, int c) {
        if (r < 0 || c < 0 || r >= grid.Length || c >= grid[0].Length || grid[r][c] != '1') return;
        grid[r][c] = '0';                       // mark visited
        Sink(r+1,c); Sink(r-1,c); Sink(r,c+1); Sink(r,c-1);
    }
    for (int r = 0; r < grid.Length; r++)
        for (int c = 0; c < grid[0].Length; c++)
            if (grid[r][c] == '1') { count++; Sink(r,c); }
    return count;
}
7/10Coin Change β€” fewest coins to make an amount (DP)

Idea: dp[a] = min coins to make amount a. Build up from 0: for each amount, try every coin. O(amount Γ— coins).

public int CoinChange(int[] coins, int amount) {
    var dp = new int[amount + 1];
    Array.Fill(dp, amount + 1);                 // "infinity"
    dp[0] = 0;
    for (int a = 1; a <= amount; a++)
        foreach (int coin in coins)
            if (coin <= a) dp[a] = Math.Min(dp[a], dp[a - coin] + 1);
    return dp[amount] > amount ? -1 : dp[amount];
}

Practice set (do in order, understand each fully):

Easy: Two Sum Β· Valid Parentheses Β· Merge Two Sorted Lists Β· Best Time to Buy/Sell Stock Β· Reverse Linked List Β· Contains Duplicate Β· Valid Anagram Β· Maximum Subarray Β· Climbing Stairs.

Medium: Group Anagrams Β· Longest Substring Without Repeating Characters Β· Product of Array Except Self Β· Binary Tree Level Order Traversal Β· Number of Islands Β· Course Schedule Β· Coin Change Β· Top K Frequent Elements Β· House Robber Β· Longest Common Subsequence.

Target: 80–100 problems, deeply understood, beats 300 rushed. Redo any you couldn't solve after a week.

1.7 Bit manipulation Lower priority 3/10

Bits are occasionally tested, especially at bigger companies. The essentials:

OperationMeaningTrick
3/10a & bANDx & 1 tests if x is odd
3/10a | bORset a bit
3/10a ^ bXORequal values cancel to 0
3/10x << nleft shiftmultiply by 2ⁿ
3/10x >> nright shiftdivide by 2ⁿ (arithmetic on signed ints β€” careful with negatives)
3/10x & (x-1)clears lowest set bitcount set bits / power-of-two check
// "Single number": every value appears twice except one β€” XOR cancels the pairs
int Single(int[] nums) { int r = 0; foreach (int n in nums) r ^= n; return r; }

// Is x a power of two? Exactly one bit set.
bool IsPowerOfTwo(int x) => x > 0 && (x & (x - 1)) == 0;

1.8 More worked problems 6/10

6/10Merge Intervals β€” combine overlapping ranges

Idea: sort by start; if the next interval starts before the current one ends, merge by extending the end. O(n log n) from the sort.

public int[][] Merge(int[][] intervals) {
    Array.Sort(intervals, (a, b) => a[0].CompareTo(b[0]));
    var res = new List<int[]>();
    foreach (var cur in intervals) {
        if (res.Count == 0 || res[^1][1] < cur[0]) res.Add(cur);
        else res[^1][1] = Math.Max(res[^1][1], cur[1]);   // overlap β†’ extend
    }
    return res.ToArray();
}
6/10Top K Frequent Elements

Idea: count frequencies in a dictionary, then keep a min-heap of size K. O(n log k).

public int[] TopKFrequent(int[] nums, int k) {
    var freq = new Dictionary<int,int>();
    foreach (int n in nums) freq[n] = freq.GetValueOrDefault(n) + 1;
    var heap = new PriorityQueue<int,int>();          // min-heap by frequency
    foreach (var kv in freq) {
        heap.Enqueue(kv.Key, kv.Value);
        if (heap.Count > k) heap.Dequeue();            // drop the least frequent
    }
    var res = new int[k];
    for (int i = k - 1; i >= 0; i--) res[i] = heap.Dequeue();
    return res;
}
6/10Reverse a Linked List

Idea: walk the list, flipping each next pointer to the previous node. O(n) time, O(1) space.

public ListNode Reverse(ListNode head) {
    ListNode prev = null, cur = head;
    while (cur != null) {
        var next = cur.next;   // save
        cur.next = prev;       // reverse pointer
        prev = cur;            // advance
        cur = next;
    }
    return prev;               // new head
}
6/10Course Schedule β€” can all courses be finished? (cycle detection)

Idea: it's a topological-sort feasibility question. Build a graph of prerequisites; if there's a cycle, it's impossible. Use Kahn's algorithm (BFS on in-degrees): repeatedly remove nodes with 0 prerequisites. If you can remove all, no cycle.

public bool CanFinish(int n, int[][] prereqs) {
    var graph = new List<int>[n];
    var indeg = new int[n];
    for (int i = 0; i < n; i++) graph[i] = new();
    foreach (var p in prereqs) { graph[p[1]].Add(p[0]); indeg[p[0]]++; }
    var q = new Queue<int>();
    for (int i = 0; i < n; i++) if (indeg[i] == 0) q.Enqueue(i);
    int done = 0;
    while (q.Count > 0) {
        int c = q.Dequeue(); done++;
        foreach (int nxt in graph[c]) if (--indeg[nxt] == 0) q.Enqueue(nxt);
    }
    return done == n;   // all scheduled β†’ no cycle
}

1.9 Rapid-fire algorithm Q&A 7/10

7/10When would you use a hash table over a balanced tree?

Hash table for O(1) average lookups when you don't need ordering. Balanced tree (or sorted structure) when you need ordered traversal, range queries, or predecessor/successor β€” those are O(log n) but ordered; a hash table can't do them.

7/10BFS vs DFS β€” which for shortest path?

BFS finds shortest paths in an unweighted graph because it explores by edge distance. DFS is useful for exhaustive traversal, cycle detection, and topological-sort implementations. Dijkstra uses a priority queue for non-negative weighted edges; Bellman-Ford can handle negative edges and detect reachable negative cycles.

7/10How do you detect a cycle in a linked list without extra memory?

Floyd's fast/slow pointers: slow moves 1, fast moves 2. If they ever meet, there's a cycle; if fast hits null, there isn't. O(n) time, O(1) space.

7/10What makes quicksort O(nΒ²) in the worst case?

A consistently bad pivot (e.g. already-sorted input with first-element pivot) makes partitions of size 0 and n-1, giving n levels of O(n) work. Randomized or median-of-three pivots make that pathological case unlikely; heapsort/mergesort guarantee O(n log n).

7/10Stable vs unstable sort β€” why care?

A stable sort preserves the relative order of equal keys. It matters when sorting by multiple keys in passes (sort by name, then by age, keeping name order within equal ages). Merge sort is stable; heapsort and typical quicksort are not.

7/10How do you find the K-th largest element efficiently?

Two ways: a min-heap of size K β†’ O(n log k); or Quickselect (partition like quicksort but recurse into one side) β†’ O(n) average, O(nΒ²) worst.

7/10Recursion vs iteration β€” trade-offs?

Recursion is cleaner for tree/divide-and-conquer problems but uses call-stack memory and can StackOverflow on deep inputs. Iteration (with an explicit stack/queue) avoids that and is often faster. Tail-recursion helps in some languages, but C# doesn't guarantee tail-call optimization.

↑ back to top

2Language & Framework Fundamentals Must know 10/100/0 βœ“

Interviewers use this round to tell a "can code" candidate from a "understands the platform" one. Below is C# / .NET, but the ideas map to any stack. Focus on why things work, because follow-up questions dig into mechanics.

2.1 OOP β€” the four pillars, explained properly 10/10

Study Card #2

Encapsulation 10/10

Keep data and the logic that changes it together, and hide the internals behind a public surface. Callers can't put the object into an invalid state. Example: a BankAccount exposes Deposit()/Withdraw() but keeps balance private so nobody sets it to a negative number directly.

Abstraction 10/10

Expose what something does, hide how. You depend on an IEmailSender interface, not on the SMTP details. This lets you swap implementations (SMTP β†’ SendGrid) without touching callers.

Inheritance 10/10

A subclass reuses and extends a base class ("is-a"). Powerful but easily abused β€” deep hierarchies become rigid. Modern advice: prefer composition (assemble behavior from small parts you inject) over inheritance.

Polymorphism 10/10

One call, many behaviors. Given Shape.Area(), a Circle and a Square each compute differently; code that loops over List<Shape> calls Area() without knowing the concrete type. Achieved via virtual methods / interface implementations.

abstract class vs interface (asked constantly):

  • 10/10Interface = primarily a contract describing available members. A class can implement many interfaces. Modern C# interfaces can also contain default implementations and static members, but they do not hold per-instance fields. Use an interface to describe a capability (IDisposable, IComparable).
  • 10/10Abstract class = a partial base with shared state/implementation plus some members subclasses must fill in. A class can inherit only one. Use it when subclasses share real code, not just a shape.
  • 10/10Rule of thumb: "can do" β†’ interface; "is a kind of" with shared code β†’ abstract class.
Study Card #3

Access modifiers, virtual/override/new, sealed, static 8/10

  • 8/10Access modifiers: public (everyone), private (same type only, the default for members), protected (type + subclasses), internal (same assembly, the default for top-level types), protected internal (subclasses OR same assembly), private protected (subclasses AND same assembly). Default to the most restrictive that works.
  • 8/10virtual vs override vs new: virtual lets a base method be overridden; override replaces it with runtime (polymorphic) dispatch, so a base-typed reference calls the derived version. new merely hides the base method β€” which one runs depends on the compile-time type of the reference. Hiding is a common source of bugs; interviewers love asking which method a Base b = new Derived() call picks.
  • 6/10sealed: on a class, prevents inheritance; on an override, stops further overriding. Communicates design intent and can enable minor devirtualization optimizations.
  • 7/10static: a static member belongs to the type, not an instance; a static class cannot be instantiated and holds only static members (e.g. utility/extension-method classes). A static constructor runs once before first use. Mutable static state is shared process-wide β€” a thread-safety and testability hazard; prefer DI singletons for shared services.

2.2 SOLID β€” each principle with a concrete fix 9/10

  • 9/10S β€” Single Responsibility. One class, one reason to change. A class that parses a file and emails results and writes to the DB should be three classes.
  • 9/10O β€” Open/Closed. Open to extension, closed to modification. Instead of a growing switch on payment type, add a new IPaymentMethod implementation β€” existing code doesn't change.
  • 9/10L β€” Liskov Substitution. A subtype must work anywhere its base type is expected. The classic violation: a Square subclassing Rectangle breaks code that sets width and height independently.
  • 9/10I β€” Interface Segregation. Prefer several small interfaces over one fat one, so implementers aren't forced to stub methods they don't use.
  • 9/10D β€” Dependency Inversion. High-level policy should not depend directly on low-level implementation details; both should depend on a useful abstraction, for example IEmailSender rather than an SMTP SDK. A DI container helps compose dependencies, but using a container alone does not guarantee good abstractions.

2.3 C# internals interviewers probe 9/10

Study Card #4

Value types vs reference types 10/10

struct, int, bool, enum, DateTime are value types β€” stored inline and copied when assigned or passed. class, arrays, string, delegates are reference types β€” the variable holds a pointer; assigning copies the pointer, not the object. This changes equality and mutation behavior: passing a struct to a method and mutating it won't affect the caller's copy; passing a class will.

Storage location vs type semantics & boxing 8/10

Do not equate β€œvalue type” with β€œstack” and β€œreference type” with β€œheap.” A value can be stored inline inside an object or array on the managed heap, and the JIT may keep locals in registers. The important distinction is copy semantics: assigning a value type copies its value; assigning a reference type copies a reference to the same object. Boxing wraps a value type in an object/interface representation and usually allocates; generics such as List<int> avoid that boxing.

Why string is immutable 8/10

Every "modification" of a string creates a new one. Benefits: safe to share across threads, usable as dictionary keys, enables interning. Cost: concatenating in a loop creates many throwaway strings β€” use StringBuilder instead.

decimal vs double 8/10

Use decimal for money and base-10 business calculations where decimal precision matters. Use double for scientific measurements and performance-sensitive floating-point math. Neither should be compared casually for exact equality after arbitrary calculations; define rounding rules explicitly.

Date and time 7/10

Use UTC for instants in storage and transport, often represented by DateTimeOffset. A local calendar time plus a time-zone identifier is different from an instant. Do not store only a UTC offset for future scheduling because daylight-saving rules can change. Inject TimeProvider so time-dependent code is testable.

IEnumerable vs IQueryable (a real bug) 9/10

IEnumerable<T> operators run in .NET; IQueryable<T> builds an expression tree that a provider such as EF Core can translate. Calling AsEnumerable() or otherwise switching to enumerable operators before a filter means that filter is no longer translated; when enumerated, SQL may fetch far more rows and C# filters them afterward. Keep translatable filtering, ordering, projection, and paging in IQueryable until execution.

LINQ & deferred execution 9/10

A LINQ query often does not run when definedβ€”it runs when enumerated (foreach, ToList(), Count()). Avoid accidental multiple enumeration, especially when the source is a database or network stream. Use Any() rather than Count() > 0 for existence, and know the semantic difference between First, Single, and their OrDefault variants. Materialize only when you need a snapshot or repeated in-memory access.

Cleanup: IDisposable & using 9/10

Managed objects that own scarce resourcesβ€”file handles, sockets, streams, timers, and database connectionsβ€”often implement IDisposable or IAsyncDisposable. A using/await using statement guarantees deterministic cleanup even if an exception is thrown. The GC reclaims managed memory; it does not replace timely disposal.

2.4 CLR, IL, JIT, assemblies & managed code 7/10

Study Card #5

From source code to execution 8/10

The C# compiler turns source code into Common Intermediate Language (CIL/IL) plus metadata inside an assembly (.dll or .exe). The Common Language Runtime (CLR) loads the assembly, verifies types, manages memory and exceptions, and the JIT compiler converts IL into native machine code as methods are executed. ReadyToRun and Native AOT can move some or all compilation ahead of time.

Assemblies and metadata 6/10

An assembly is a deployment/versioning unit containing IL, type metadata, resources, and a manifest. Reflection reads that metadata at runtime; attributes attach metadata that frameworks such as ASP.NET Core and EF Core inspect.

Generics, constraints and variance 7/10

Generics provide compile-time type safety and avoid many casts and boxing allocations. Constraints such as where T : class, struct, new(), or an interface describe what T must support. Covariance (out) allows producing a more-derived type; contravariance (in) allows consuming a less-derived type.

Equality and hashing 8/10

If a type is used as a dictionary key or in a hash set, equal objects must return the same hash code. Override Equals and GetHashCode together, or implement IEquatable<T>. Never mutate fields that participate in a key's hash while it is inside a hash-based collection.

Exceptions 9/10

Use exceptions for exceptional failures, not normal branching. Catch only when you can add context, translate, recover, or clean up. Use throw; to preserve the original stack trace; throw ex; resets it. At API boundaries, map expected failures to suitable HTTP responses and let an exception handler produce a safe ProblemDetails response.

2.5 Async / await β€” what actually happens 10/10

A web server has a limited ThreadPool. When a genuinely asynchronous I/O operation is incomplete, await records the continuation and returns control without blocking a request thread. When the I/O completes, execution resumes later, possibly on a different ThreadPool thread. This improves throughput; it does not make CPU-heavy work faster.

public async Task<User?> GetUserAsync(int id, CancellationToken cancellationToken) {
    // The request thread is not blocked while asynchronous database I/O is pending.
    var user = await _db.Users.FindAsync(new object[] { id }, cancellationToken);
    return user;
}

Avoid sync-over-async: .Result, .Wait(), and unnecessary Task.Run consume threads and can cause ThreadPool starvation under load. Classic SynchronizationContext deadlocks are common in UI apps and legacy ASP.NET; ASP.NET Core has no request SynchronizationContext by default, so starvation is the usual risk there. Prefer async all the way.

  • 10/10Task vs Thread: a Task represents an asynchronous operation and its eventual result; it does not necessarily own or run on a thread. A Thread is an OS execution resource. I/O tasks can be pending with no thread blocked.
  • 10/10I/O-bound vs CPU-bound: await asynchronous APIs for database, file, and network I/O. Use Task.Run only when you intentionally move CPU-bound work to the ThreadPool; in a web server, sustained CPU work is usually better moved to a worker service.
  • 9/10Composition: use Task.WhenAll for independent operations, but do not create unbounded parallelism. Limit fan-out with SemaphoreSlim, a channel, or a bounded worker queue.
  • 10/10Cancellation: pass CancellationToken through every cancellable call, including EF Core and HttpClient. In APIs, propagate HttpContext.RequestAborted. Cancellation is cooperative and often throws OperationCanceledException.
  • 9/10Avoid async void: except for event handlers, return Task so callers can await failures. Consider ValueTask only for measured hot paths where operations frequently complete synchronously.
  • 6/10ConfigureAwait: ASP.NET Core has no request SynchronizationContext, so ConfigureAwait(false) is usually unnecessary in application code. It can still be appropriate in reusable libraries that should not depend on a caller's context.
  • 9/10Thread safety: shared mutable state may require lock, Interlocked, concurrent collections, or immutability. You cannot await inside a C# lock; use SemaphoreSlim.WaitAsync for asynchronous coordination.

2.6 ASP.NET Core β€” the request lifecycle & architecture 10/10

Kestrel accepts HTTP requests, commonly behind a reverse proxy or cloud load balancer. A request then flows through the ordered middleware pipeline. Middleware can inspect or short-circuit the request, call the next component, and inspect the response on the way back. Typical ordering puts exception handling early, then forwarded headers/HTTPS/static files as needed, routing, authentication, authorization, and endpoints. Exact ordering depends on the application.

// Interviewers often ask you to sketch a custom middleware:
app.Use(async (context, next) => {
    var sw = Stopwatch.StartNew();
    await next(context);                        // run the rest of the pipeline
    app.Logger.LogInformation("{Method} {Path} => {Status} in {Ms} ms",
        context.Request.Method, context.Request.Path,
        context.Response.StatusCode, sw.ElapsedMilliseconds);
});

Dependency Injection lifetimes (a top interview trap):

  • 10/10Transient β€” a fresh instance every time it's requested. Use for lightweight, stateless services.
  • 10/10Scoped β€” one instance per HTTP request. DbContext is scoped.
  • 10/10Singleton β€” one instance for the whole app lifetime. Use for caches/config; must be thread-safe.

The classic bug: injecting a scoped DbContext into a singleton. The singleton captures one DbContext forever, which is not thread-safe and leaks stale data across requests β€” a "captive dependency". The DI container will actually throw if it detects this at startup in development.

  • 8/10Controllers vs Minimal APIs: both are first-class. Minimal APIs are concise and fit small focused services; controllers provide conventions, filters, and organization for larger APIs. Choose by complexity and team conventionsβ€”not by a blanket performance rule.
  • 5/10Keyed DI services: when several implementations share one interface, register and resolve keyed services with AddKeyedScoped/AddKeyedSingleton and [FromKeyedServices]. Prefer ordinary constructor injection when one implementation is enough; excessive runtime key selection can hide dependencies.
  • 8/10Middleware vs filters: middleware is framework-wide and runs before MVC/endpoint-specific behavior. MVC filters have action/controller context. Endpoint filters provide similar interception for Minimal APIs.
  • 9/10Binding, validation and errors: map route/query/header/body data to request models, validate at the boundary, and return standardized RFC 7807/9457-style ProblemDetails. Use global exception handling such as IExceptionHandler; do not leak stack traces.
  • 8/10Serialization: ASP.NET Core commonly uses System.Text.Json. Return DTOs rather than EF entities, define naming/null/enum behavior intentionally, prevent reference cycles, and use streaming/source generation only when profiling justifies it.
  • 10/10Authentication and authorization: authentication builds a ClaimsPrincipal; authorization evaluates roles, claims, policies, or resource-based handlers. UseAuthentication() must run before UseAuthorization().
  • 8/10OpenAPI: expose an OpenAPI document for API discovery, generated clients, and testing. Know request/response contracts, content negotiation, versioning strategy, and backward compatibility.
  • 9/10IHttpClientFactory: do not create and dispose an HttpClient per request. Use factory-created named/typed clients, or a long-lived client configured with SocketsHttpHandler.PooledConnectionLifetime, so connections are reused without pinning DNS indefinitely. Add explicit timeouts and resilience policies.
  • 8/10Background work: never fire-and-forget request-scoped work with unobserved Task.Run. Use a bounded queue plus BackgroundService, or an external broker/worker. Create a DI scope inside the worker when scoped services are needed.
  • 9/10Configuration and options: configuration is layered from files, environment variables, secret stores, and command-line values. Bind to IOptions<T>, validate options at startup, and use IOptionsSnapshot/IOptionsMonitor only when reload semantics are needed.
  • 9/10Operations: use structured ILogger logs, OpenTelemetry traces/metrics, correlation or trace IDs, and separate liveness/readiness health checks. Never log passwords, tokens, or sensitive personal data.

2.7 Testing 8/10

  • 8/10Unit tests: test behavior of a small unit quickly. Use fakes/mocks at real external boundaries; do not mock every internal class or assert implementation details.
  • 9/10Integration tests: use WebApplicationFactory<Program> to run the real ASP.NET Core pipeline. EF Core's InMemory provider is not relational and can hide constraint, transaction, translation, and SQL differences. Use SQLite for lightweight relational tests or a disposable instance of the production engine when fidelity matters. Testcontainers is valuable when Docker is available; it is an option, not a universal requirement.
  • 6/10Contract and end-to-end tests: contract tests protect service/API compatibility; end-to-end tests cover a few critical user journeys. Keep the suite deterministic and isolate test data.
  • 8/10Structure: Arrange, Act, Assert. Name tests by observable behavior, for example Withdraw_WhenBalanceTooLow_Throws. Include happy paths, boundaries, failures, authorization, cancellation, and concurrency where relevant.
  • 6/10Tools: xUnit, NUnit, or MSTest; a mocking library when useful; and built-in or third-party assertion helpers. The tool matters less than readable, stable tests.

2.8 Checkpoint interview Q&A 8/10

8/10What's the difference between abstract class and interface?

An interface is a contract with (traditionally) no implementation or state; a class can implement many. An abstract class can hold fields, constructors, and shared method bodies, but a class can inherit only one. Use an interface for a capability that unrelated types can have; use an abstract class when subclasses genuinely share code and identity ("is-a"). Since C# 8, interfaces can have default methods, but they still can't hold instance state.

8/10Explain IEnumerable vs IQueryable with a bug.

IEnumerable runs LINQ in memory; IQueryable translates it to SQL. Bug: IEnumerable<User> users = db.Users; var active = users.Where(u => u.IsActive); β€” because it's typed as IEnumerable, EF loads the whole Users table then filters in C#. Keep it IQueryable and the Where becomes a SQL WHERE, fetching only matching rows.

8/10Why should an ASP.NET Core API avoid .Result and .Wait()?

They block ThreadPool threads while asynchronous work is pending, reducing throughput and potentially causing ThreadPool starvation under load. ASP.NET Core has no request SynchronizationContext by default, so the classic UI/legacy-ASP.NET deadlock is not the normal explanation, although deadlocks remain possible with custom synchronization or locks. Await the operation instead.

8/10What is a race condition and how do you prevent it?

When two threads access shared mutable state concurrently and the outcome depends on timing β€” e.g. both read a counter as 5, both write 6, losing an increment. Prevent it with a lock, atomic operations (Interlocked.Increment), concurrent collections, or by making the state immutable so there's nothing to corrupt.

8/10Give a bug caused by the wrong DI lifetime.

Registering a service as Singleton that depends on a Scoped DbContext. The singleton holds one DbContext for the app's life; it's used across many concurrent requests (not thread-safe) and never refreshes, causing data corruption and stale reads. Fix: make the service Scoped, or resolve a fresh DbContext per operation via a factory.

2.9 More C# features interviewers ask about 8/10

Study Card #6

Delegates, Func, Action, events 8/10

A delegate is a type-safe function pointer. Func<int,int> returns a value; Action<T> returns void; Predicate<T> returns bool. Events are a publisher/subscriber wrapper over delegates so subscribers can only +=/-=, not invoke or overwrite.

Lambdas & closures 8/10

A lambda (x => x * 2) is an inline function. A closure captures variables from its surrounding scope β€” a classic bug is capturing a loop variable and finding all lambdas share the final value (fixed by copying into a local inside the loop; modern C# fixes foreach).

record vs class vs struct 9/10

class = reference type with reference equality by default. struct = value type, copied by value, best when small and preferably immutable. record class adds value-based equality and concise nondestructive mutation with with; it is not automatically immutable unless its members are init-only/read-only. record struct is the value-type form.

ref, out, in, params 6/10

ref passes by reference (read/write), out must be assigned by the callee (e.g. TryParse), in passes a readonly reference (avoids copying big structs), params accepts a variable number of arguments.

yield return (iterators) 7/10

yield return builds a lazy sequence β€” values are produced on demand as the caller enumerates, without materializing a full list. Great for streaming large data.

Extension methods 7/10

Add methods to existing types without modifying them (static method with a this first parameter). All of LINQ is extension methods on IEnumerable<T>.

Pattern matching & switch expressions 7/10

Modern C# lets you branch on type/shape: obj switch { Circle c => c.R, Square s => s.Side, _ => 0 } β€” concise and exhaustive.

Nullable reference types 8/10

string? vs string lets the compiler warn about possible nulls at compile time, reducing NullReferenceExceptions β€” the "billion-dollar mistake".

Reflection and attributes 6/10

Reflection inspects types and metadata at runtime; attributes attach metadata used by ASP.NET Core routing, validation, serialization, and EF Core mapping. Reflection is powerful but slower, harder to trim/AOT, and should not replace ordinary polymorphism.

Span<T> / Memory<T> 4/10

Allocation-free views over arrays/strings for high-performance parsing β€” slice without copying. Mentioning these signals depth.

IAsyncEnumerable<T> 6/10

Combines IEnumerable with async. Great for streaming data from a database or API one chunk at a time without loading it all into memory. You consume it with await foreach.

Recent language features Lower priority 4/10

Primary constructors and collection expressions arrived in C# 12; C# 14 adds features such as extension members and the field-backed-property field keyword. Know the version used by the employer, but expect interviews to value async, generics, LINQ, nullable references, equality, and runtime behavior much more than syntax trivia.

2.10 Garbage collection (be able to explain it) 8/10

.NET manages memory automatically with a generational, tracing garbage collector:

  • 8/10Gen 0 β€” new, short-lived objects; collected frequently and cheaply.
  • 8/10Gen 1 β€” survivors of a Gen 0 collection; a buffer between short- and long-lived.
  • 8/10Gen 2 β€” long-lived objects (caches, singletons); collected rarely.
  • 8/10Large Object Heap (LOH) β€” large allocations (commonly β‰₯85 KB) are collected with Gen 2 and are compacted less routinely, so repeated large allocations can cause fragmentation and long pauses.
  • 7/10Workstation vs Server GC β€” Server GC (the ASP.NET Core default) uses per-core heaps and parallel collection for throughput at the cost of memory; Workstation GC favors a smaller footprint. Gen 0/1 collections are frequent and cheap; blocking full Gen 2 collections are what cause noticeable pauses.

The idea (the "generational hypothesis"): most objects die young, so collecting Gen 0 often and Gen 2 rarely is efficient. You rarely call GC.Collect() manually β€” instead you avoid leaks: unsubscribe from events, dispose IDisposable, and don't hold references longer than needed. A memory leak in .NET is usually an object still referenced somewhere (e.g. a static list or an event handler) so the GC can't reclaim it.

Managed vs unmanaged resources: the GC handles managed memory automatically, but types like FileStream, Socket, and DbConnection are managed wrappers around unmanaged OS resources β€” release them deterministically with Dispose()/using. Finalizers are only a safety net: they run late (if at all) and keep objects alive an extra GC cycle.

10/10Value type vs reference type β€” the correct distinction

Assignment and by-value parameter passing copy the value-type data, but copy the reference for reference types, so both reference variables can point to the same object. Either kind may be stored on the managed heap depending on context; storage location is not the definition.

8/10What is boxing and why avoid it?

Boxing wraps a value type in a heap object to treat it as object (or a non-generic interface). It allocates and adds GC pressure; in hot loops it's a real cost. Generics (List<int>) avoid it.

7/10const vs readonly?

const is compile-time, baked into callers, must be a literal. readonly is set at runtime (in the constructor) and can differ per instance. Prefer readonly for values that might change between builds.

8/10== vs .Equals()?

For reference types == is reference equality by default (unless overloaded, as string does), while .Equals() can be overridden for value equality. records give value equality for both automatically.

↑ back to top

3Databases Must know 10/100/0 βœ“

Nearly every backend interview has a database round, and many ask you to write SQL on a whiteboard or screen share. This section gives you the mechanics and the actual queries so you can reproduce them.

3.1 Relational fundamentals & normalization 8/10

  • 8/10Primary key (PK) β€” uniquely identifies a row (often an auto-increment id or a GUID).
  • 8/10Foreign key (FK) β€” a column pointing at another table's PK; the database enforces that the referenced row exists (referential integrity).
  • 8/10Relationships: one-to-one, one-to-many (a user has many orders β†’ the FK lives on orders), many-to-many (students ↔ courses β†’ needs a junction table enrollments).

Normalization removes redundancy so data can't contradict itself:

  • 8/101NF β€” every column holds one atomic value (no comma-separated lists in a cell).
  • 8/102NF β€” no column depends on only part of a composite key.
  • 8/103NF β€” no non-key column depends on another non-key column (store city once in an addresses table, don't repeat it per order).
  • 8/10Denormalization β€” deliberately duplicating data to avoid expensive joins on read-heavy paths. It's a performance trade-off you now maintain by hand.

3.2 SQL you must write fluently β€” with full solutions 10/10

The examples are mostly portable SQL. Dialects differ: SQL Server commonly uses TOP or OFFSET … FETCH, while PostgreSQL/MySQL use LIMIT. State which dialect you are using in an interview.

-- Filtering, sorting, limiting
SELECT TOP (10) name, email FROM users
WHERE country = 'NO' AND is_active = 1
ORDER BY created_at DESC;

-- Aggregation: WHERE filters ROWS, HAVING filters GROUPS
SELECT country, COUNT(*) AS user_count, AVG(age) AS avg_age
FROM users
WHERE is_active = 1
GROUP BY country
HAVING COUNT(*) > 100;

Join types (know exactly what each returns) 10/10

JoinReturns
10/10INNER JOINOnly rows that match in both tables.
10/10LEFT JOINAll left rows; NULLs where the right has no match. (Great for "find records with none".)
10/10RIGHT JOINAll right rows; NULLs where the left has no match.
10/10FULL OUTER JOINAll rows from both, matched where possible.
10/10CROSS JOINEvery combination (Cartesian product).
10/10Find the 2nd highest salary

Two standard answers β€” know both:

-- Simple, portable
SELECT MAX(salary) FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);

-- General "Nth highest" via a window function
SELECT DISTINCT salary FROM (
    SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
    FROM employees
) t
WHERE rnk = 2;
10/10Find users who have never placed an order

LEFT JOIN and keep rows where the right side is NULL:

SELECT u.id, u.name
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.id IS NULL;
10/10Highest-paid employee(s) per department

Use DENSE_RANK if ties should all be returned; use ROW_NUMBER only when exactly one deterministic winner is required:

SELECT department_id, name, salary FROM (
    SELECT department_id, name, salary,
           DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS salary_rank
    FROM employees
) t
WHERE salary_rank = 1;
10/10Find duplicate emails
SELECT email, COUNT(*) AS n
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

3.3 Indexes β€” how they actually speed things up 10/10

An index is an auxiliary access structureβ€”commonly a B-treeβ€”that can let the optimizer seek to matching rows instead of scanning every row. Complexity is often described as roughly O(log n), but real performance also depends on selectivity, pages read, key lookups, caching, and how many rows are returned.

  • 10/10Trade-off: reads get faster, but every INSERT/UPDATE/DELETE must also update the index, and indexes use storage. Don't index everything.
  • 8/10Clustered vs non-clustered: in SQL Server, the clustered index organizes table rows by its key and there can be only one; non-clustered indexes are separate structures. Other engines use different storage models, so do not present this as universal SQL behavior.
  • 10/10Composite index β€” spans multiple columns; the order matters (leftmost-prefix rule): an index on (country, city) helps queries filtering by country or country + city, but not by city alone.
  • 10/10Covering and filtered indexes: included columns can let SQL Server satisfy a query from the index alone; filtered indexes target a selective subset such as active rows.
  • 10/10SARGability: write predicates the engine can seek on. For example, WHERE CreatedAt >= @start is usually better than wrapping CreatedAt in a function. Use the actual execution plan and measured readsβ€”not guessesβ€”to verify improvement.

3.4 Transactions & ACID 9/10

A transaction groups statements so they all commit or all roll back β€” critical for things like transferring money (debit one account, credit another; you can't do just half).

  • 9/10A β€” Atomicity: all steps succeed or none do.
  • 9/10C β€” Consistency: a committed transaction preserves declared constraints and application invariants when the transaction logic is correct.
  • 9/10I β€” Isolation: controls how concurrent transactions observe and interfere with one another.
  • 9/10D β€” Durability: once committed, data survives a crash (written to disk/log).

Isolation levels trade correctness against concurrency, from weakest to strongest:

LevelPreventsStill allows
9/10Read Uncommittednothingdirty reads (see uncommitted data)
9/10Read Committeddirty readsnon-repeatable reads
9/10Repeatable Readnon-repeatable readsphantom reads
9/10Serializableeverything (acts serial)β€” (most locking/contention)

Exact behavior is database-specific. SQL Server also offers snapshot-based isolation; PostgreSQL implements some named levels using multiversion concurrency control. In an interview, explain the anomaly you need to prevent rather than assuming every engine behaves identically.

3.5 The N+1 problem & EF Core pitfalls 10/10

The most-asked ORM question. With lazy-loading proxies enabled, you fetch a list (1 query), then access a related entity per item (N more queries) β†’ 1 + N round-trips that can crush performance. EF Core does not enable lazy loading automatically.

// BAD β€” N+1: one extra query per order to load its user
var orders = db.Orders.ToList();
foreach (var o in orders)
    Console.WriteLine(o.User.Name);      // lazy loads each time

// GOOD β€” project only the columns the endpoint needs.
var orders = await db.Orders
    .Select(o => new { o.Id, UserName = o.User.Name })
    .ToListAsync(cancellationToken);
Study Card #7

EF Core Essentials for Interviews 10/10

  • 9/10Tracking vs no-tracking: tracking is useful when loaded entities will be updated. Use AsNoTracking() for read-only entity queries when identity resolution/change tracking is unnecessary; projection to DTOs is often even better. Measure before making a global rule.
  • 9/10IQueryable vs IEnumerable: ToList(), First(), enumeration, and similar terminal operations execute the query. AsEnumerable() does not execute immediately, but later LINQ operators run in .NET rather than being translated, which can cause far more data to be fetched.
  • 9/10Query shape: use projection for API responses. Include is appropriate when materializing entity graphs, but multiple collection includes can create a cartesian explosion. Consider AsSplitQuery() and understand that several intentional queries can be better than one huge join.
  • 9/10Loading: know eager loading (Include), explicit loading, and optional lazy loading. Avoid accessing navigation properties in loops without knowing which SQL is generated.
  • 9/10Migrations: create with dotnet ef migrations add and apply with dotnet ef database update. For controlled production deployments, reviewed idempotent scripts or migration bundles are often safer than every app instance migrating on startup.
  • 9/10Concurrency: Use a [Timestamp] or [ConcurrencyCheck] property. EF checks this token during UPDATE and throws a DbUpdateConcurrencyException if another user modified the row first (optimistic locking).
  • 9/10Transactions: one relational SaveChanges call is transactional by default. Use an explicit transaction only when several operations must share a larger atomic boundary, and keep that boundary short.
  • 7/10Set-based updates: EF Core 7+ adds ExecuteUpdateAsync/ExecuteDeleteAsync for bulk UPDATE/DELETE without loading entities. They execute immediately, bypass change tracking, and do not participate in SaveChanges β€” combine them with tracked changes only inside an explicit transaction.
  • 6/10DbContext pooling: AddDbContextPool can reduce context setup allocations in measured high-throughput services. A pooled context is reset and reused, so do not retain request-specific mutable state on it; pooling is an optimization, not a substitute for efficient SQL.

3.6 SQL vs NoSQL β€” how to choose 7/10

SQL (relational)NoSQL
7/10SchemaExplicit and database-enforcedOften flexible or application-enforcedβ€”not literally β€œno schema”
7/10StrengthsRelationships, joins, ACID, complex queriesHorizontal scale, flexible shapes, high throughput
7/10ExamplesPostgreSQL, SQL Server, MySQLMongoDB (document), Redis (key-value), Cassandra (wide-column), Neo4j (graph)
7/10Choose whenData is relational & consistency matters (most business apps)Huge scale, flexible/evolving schema, or a specific access pattern (caching, time-series)

Many real systems use both (polyglot persistence): PostgreSQL for core data, Redis for caching/sessions, a search engine for full-text.

3.7 Full interview Q&A 8/10

8/10Difference between WHERE and HAVING?

WHERE filters individual rows before grouping; HAVING filters groups after GROUP BY and can use aggregates like COUNT(*). You can't put an aggregate in WHERE.

8/10What's an index and its downside?

An index is an auxiliary access structure, commonly a B-tree, that can reduce pages read for selective filters, joins, and ordering. It consumes storage and write/maintenance cost, and a low-selectivity or badly ordered index may not help. Verify with actual plans and measurements.

8/10INNER vs LEFT JOIN β€” when do you need LEFT?

When you want rows from the left table even if there's no match on the right β€” e.g. "list all customers and their order count, including customers with zero orders". An INNER JOIN would silently drop the zero-order customers.

8/10How do you fix N+1 in EF Core?

Prefer a projection with Select when returning DTOs, or eager-load the required graph with Include. Inspect generated SQL and query counts. The goal is a deliberate, bounded query shapeβ€”not always exactly one query, because split queries can be the safer choice.

3.8 Advanced SQL you should recognize 7/10

CTEs (Common Table Expressions) & recursion 7/10

A CTE is a named query expression scoped to one statement that can improve readability. It is not necessarily materialized; the optimizer may inline or otherwise transform it. Recursive CTEs can walk hierarchies such as org charts and category trees.

-- Readable multi-step query
WITH active_users AS (
    SELECT id, name FROM users WHERE is_active = 1
),
big_spenders AS (
    SELECT user_id, SUM(total) AS spent FROM orders GROUP BY user_id HAVING SUM(total) > 1000
)
SELECT a.name, b.spent
FROM active_users a JOIN big_spenders b ON b.user_id = a.id;

Window functions (very common in senior interviews) 8/10

They compute across a set of rows related to the current row without collapsing them (unlike GROUP BY):

  • 8/10ROW_NUMBER() β€” unique sequential number per partition.
  • 8/10RANK() / DENSE_RANK() β€” ranking with/without gaps on ties.
  • 8/10LAG() / LEAD() β€” previous/next row's value (great for month-over-month deltas).
  • 8/10SUM() OVER (...) β€” running totals.
-- Running total of order amounts per user, in date order
SELECT user_id, created_at, total,
       SUM(total) OVER (PARTITION BY user_id ORDER BY created_at) AS running_total
FROM orders;

Subqueries vs JOINs 7/10

Many equivalent queries are transformed into similar plans by modern optimizers; neither syntax is inherently faster. Correlated subqueries can become expensive if repeatedly evaluated. EXISTS clearly expresses an existence check and avoids some NULL surprises, while IN may be equally efficient. Compare actual plans and measured reads.

Views & stored procedures 6/10

A view is a stored query definition selected from like a table; it can simplify access and restrict exposed columns. A stored procedure is server-side SQL code with parameters and permissions. Both ad-hoc parameterized SQL and procedures can use cached execution plans, so β€œstored procedures are precompiled and therefore always faster” is not a reliable rule.

NULLs, constraints and set operations 7/10

  • 7/10NULL means unknown/missing, so use IS NULL, not = NULL. SQL uses three-valued logic; predicates involving NULL may evaluate to unknown.
  • 7/10Use NOT NULL, UNIQUE, CHECK, foreign keys, and appropriate defaults to protect invariants close to the data.
  • 7/10UNION removes duplicates; UNION ALL keeps them and is usually cheaper.
  • 7/10For large ordered result sets, keyset pagination is usually more stable and efficient than deep OFFSET paging.

3.9 Locking, deadlocks & concurrency control 8/10

  • 8/10Pessimistic locking β€” acquire locks so conflicting work waits. Syntax is engine-specific: PostgreSQL/MySQL support forms of SELECT ... FOR UPDATE; SQL Server uses transaction isolation and locking behavior/hints. Safe for some workflows but reduces concurrency.
  • 8/10Optimistic concurrency β€” don't hold a lock while the user works; include a version/timestamp predicate in the update. If no row is updated, resolve or retry the conflict. EF Core supports this when you configure a concurrency token.
  • 8/10Deadlock β€” transaction A locks row 1 then wants row 2; transaction B locks row 2 then wants row 1. Neither proceeds. The DB detects it and kills one ("deadlock victim"). Avoid by always acquiring locks in a consistent order and keeping transactions short.

3.10 Scaling & performance 7/10

  • 7/10Replication β€” primary handles writes, read replicas serve reads (eventual consistency lag to watch for).
  • 7/10Partitioning/sharding β€” split a huge table by a key (range, hash, or geography). Trade-off: cross-shard queries and joins get hard.
  • 7/10Query tuning β€” inspect the actual execution plan and logical reads, select only needed columns, use selective/SARGable predicates, avoid accidental cartesian products, and use keyset pagination for deep pages.
  • 7/10Connection pooling β€” ADO.NET providers normally pool physical connections. Open late, dispose promptly, and let pooling reuse them; a short-lived DbContext does not imply a new physical connection every time.
7/10GROUP BY vs window function β€” when each?

GROUP BY collapses rows into one per group (you lose the detail rows). A window function keeps every row but adds an aggregate/rank alongside it. Use window functions when you need "the row and its rank/running total".

7/10How would you speed up a slow query?

Reproduce with representative parameters, inspect the actual plan, duration, waits, and logical reads, then fix the measured cause: poor cardinality estimates, non-SARGable predicates, missing/unused indexes, excess columns/rows, blocking, spills, bad joins, N+1 round-trips, or stale statistics. Cache or precompute only after the query and access pattern are understood.

7/10Optimistic vs pessimistic concurrency?

Optimistic concurrency checks a version when writing and resolves conflicts after they occur, which suits many disconnected web workflows. Pessimistic concurrency holds locks to prevent conflicting access, which may be necessary for short high-contention operations but reduces throughput and can deadlock. Choose by invariant, contention, and transaction duration.

7/10What causes a deadlock and how do you prevent it?

Two transactions acquire the same locks in opposite orders and wait on each other. Prevent by acquiring resources in a consistent order, keeping transactions short, using lower isolation where safe, and adding retry logic for the deadlock victim.

↑ back to top

4System Design & Backend Architecture Mid-level+ 8/100/0 βœ“

For junior/mid roles this is usually "design a REST API" or "how would you structure this feature". For senior roles it's a full "design Twitter/Uber" round. Either way, learn the vocabulary below and the repeatable method β€” then rehearse the full walkthrough at the end.

4.1 REST API design 9/10

  • 9/10Resources are nouns; HTTP methods express semantics:
    GET /users (list) Β· GET /users/42 (one) Β· POST /users (create/process) Β· PUT /users/42 (create or replace at a known URI) Β· PATCH /users/42 (partial change) Β· DELETE /users/42.
  • 9/10Status codes: 200 OK Β· 201 Created Β· 204 No Content Β· 400 Bad Request Β· 401 Unauthorized (not logged in) Β· 403 Forbidden (logged in, not allowed) Β· 404 Not Found Β· 409 Conflict (e.g. duplicate) Β· 422 Unprocessable Β· 429 Too Many Requests Β· 500 Server Error Β· 503 Unavailable.
  • 9/10Statelessness: each request carries everything needed (e.g. an auth token); the server keeps no per-client session in memory, so any server can handle any request β€” that's what makes horizontal scaling possible.
  • 9/10Idempotency: PUT and DELETE are idempotent by HTTP semantics; GET and HEAD are also safe. POST is usually not idempotent, and PATCH depends on the patch operation. Use an idempotency key for retried commands such as payments.
  • 9/10Contracts: validate at the boundary, return ProblemDetails, publish OpenAPI, and preserve backward compatibility. Use ETags/If-Match for conditional updates where lost updates matter.
  • 9/10Collections: filter and sort explicitly, cap page size, and prefer cursor/keyset pagination for large changing datasets. Version only when a breaking contract change cannot be evolved compatibly.

4.2 Authentication & Authorization (JWT deep dive) 9/10

AuthN = "who are you?" Β· AuthZ = "what are you allowed to do?"

JWT (JSON Web Token) is one access-token format, not an authentication protocol by itself. A common flow is:

  1. 9/10User logs in with credentials; server verifies them.
  2. 9/10An authorization server issues a signed access token containing limited claims and an expiry.
  3. 9/10The client sends it to the resource API, commonly in the HTTP Authorization header using the Bearer scheme (Authorization: Bearer <token>).
  4. 9/10The API validates the allowed signing algorithm, signature, issuer, audience, lifetime, and required claims before authorizing the request.
  5. 9/10Short-lived access tokens limit exposure. Refresh tokens require secure storage, rotation, reuse detection, revocation, and server-side records.

A signed JWT has three parts: header.payload.signature, base64url-encoded. The payload is readable by anyone (not encrypted) β€” never put secrets in it. Security comes from the signature: tampering invalidates it.

  • 9/10OAuth 2.0 is an authorization framework for obtaining delegated access tokens; OpenID Connect (OIDC) adds authentication and identity claims. For browser/mobile public clients, know Authorization Code + PKCE.
  • 9/10JWT trade-off: local validation can avoid a database lookup, but immediate revocation is harder. Sensitive systems may use reference tokens/introspection or a revocation strategy.
  • 8/10Storage: do not automatically recommend localStorage. Browser apps often use secure HttpOnly, Secure, appropriate SameSite cookies or a backend-for-frontend; the right choice depends on XSS, CSRF, and architecture.
  • 9/10Passwords: prefer ASP.NET Core Identity or an external identity provider. Use adaptive salted password hashing; never design a custom password scheme.

4.3 Caching 8/10

Store expensive results somewhere faster so you do not repeatedly compute or fetch them. Layers include HTTP/browser and CDN caches, per-instance IMemoryCache, and shared IDistributedCache/Redis. In-memory cache is fastest but not shared across replicas; distributed cache adds network and operational cost.

Cache-aside is the common pattern:

value = cache.Get(key);
if (value == null) {              // cache miss
    value = db.Load(key);         // go to the source
    cache.Set(key, value, ttl);   // populate for next time
}
return value;
  • 7/10ASP.NET Core output caching: AddOutputCache/UseOutputCache can cache complete endpoint responses with policies for expiry, vary-by values, tags, and invalidation. Cache only responses that are safe to reuse; authenticated or user-specific output needs explicit partitioning or should not be cached.

Correctness comes first: define acceptable staleness, TTL, invalidation, key design, serialization, and what happens when the cache is unavailable. Prevent a cache stampede with single-flight locking, stale-while-revalidate, or randomized TTLs. Never treat Redis as automatically faster for every object or as the only durable copy unless the design explicitly supports that.

4.4 Scaling 7/10

  • 7/10Vertical scaling β€” a bigger machine (more CPU/RAM). Simple, but has a ceiling and a single point of failure.
  • 7/10Horizontal scaling β€” more machines behind a load balancer that spreads requests. Needs stateless servers (or a shared session/cache store) so any server can serve any request.
  • 7/10Database scaling:
    • 7/10Read replicas β€” copies that serve read traffic; writes go to the primary and replicate out (eventual consistency).
    • 7/10Sharding/partitioning β€” split data across DBs by a key (e.g. user id range) when one DB can't hold it all.
    • 7/10Connection pooling β€” reuse a pool of DB connections instead of opening one per request.
  • 7/10CDN β€” caches static content at edge locations near users to cut latency.

4.5 Async processing & message queues 8/10

Slow or unreliable work (sending email, processing images, generating reports, calling a flaky third party) shouldn't block the user's request. Put a message on a queue and let background workers process it.

  • 8/10Producer β†’ queue β†’ consumer. The API returns immediately; workers handle the job. This decouples services and smooths traffic spikes (the queue absorbs bursts).
  • 8/10Delivery guarantees: most queues are at-least-once, so a message can be delivered twice β€” make consumers idempotent (processing the same message twice has no extra effect).
  • 8/10Dead-letter queue β€” messages that keep failing get moved aside for inspection instead of blocking the queue.
  • 8/10Backpressure and ordering: bound queues and consumer concurrency so producers cannot exhaust memory. Ordering is usually guaranteed only within a partition/session, not globally.
  • 5/10In-process producer/consumer: System.Threading.Channels provides asynchronous bounded queues for work inside one process. A bounded channel gives backpressure and fits a BackgroundService; use a durable external broker when work must survive process failure or cross service boundaries.
  • 8/10Failure handling: use bounded retries with backoff, detect poison messages, include correlation and message IDs, and monitor queue ageβ€”not just queue length. β€œExactly once” normally requires application-level idempotency and transactional design.
  • 6/10Tools: RabbitMQ, Azure Service Bus, AWS SQS, Kafka (Kafka is really a distributed log, great for event streaming).

4.6 Architecture styles & .NET ecosystem 8/10

  • 8/10Monolith β€” one deployable app. Simple to build, test, and deploy; great to start with. Downsides: one small change redeploys everything, and you can't scale parts independently.
  • 8/10Modular monolith β€” one deployment with explicit module boundaries and controlled dependencies. It preserves simple operations while making later extraction possible; this is often a better default than immediate microservices.
  • 8/10Microservices Role-dependent β€” independently deployable services can support team autonomy and targeted scaling, but introduce network failure, data ownership, versioning, observability, and operational complexity. Start with clear boundaries and a concrete reason.
  • 8/10Layered (n-tier): Controller/API β†’ Application/Service β†’ Domain β†’ Data-access. Each layer only talks to the one below.
  • 8/10Clean / Hexagonal: the domain sits at the center with no dependencies; infrastructure (DB, HTTP, queues) plugs in at the edges and dependencies point inward. Very common in modern .NET.
  • 8/10SignalR: .NET's library for real-time web functionality. Uses WebSockets under the hood with fallbacks. Great for chat apps, live dashboards, or progress notifications.
  • 8/10YARP Optional β€” a customizable .NET reverse-proxy toolkit. Know it only if the role or existing architecture uses it; reverse-proxy and gateway concepts matter more than the product name.

4.7 Reliability, observability & CAP 8/10

  • 8/10Observability: logs explain events, metrics expose trends and saturation, and traces follow work across dependencies. Use OpenTelemetry and propagate trace context rather than inventing isolated correlation IDs.
  • 8/10SLI/SLO/SLA: an SLI is a measured indicator such as latency or error rate; an SLO is the target; an SLA is an external commitment. Error budgets guide how much unreliability is acceptable.
  • 8/10Recovery: RTO is the target time to restore service; RPO is the maximum acceptable data-loss window. Backups are not enoughβ€”restore them in tests.
  • 8/10Resilience: start with deadlines/timeouts. Retry only transient, safe/idempotent operations, with exponential backoff and jitter. Add circuit breakers, concurrency limits, rate limiting, and graceful degradation. Modern .NET can use resilience handlers built on Polly.

CAP theorem, accurately: when a network partition separates nodes, a distributed data system cannot guarantee both linearizable consistency and that every request receives a non-error response. It must favor consistency or availability for the affected operation until the partition heals. Outside a partition, CAP does not force a permanent β€œpick two” choice, and different features in one system can make different trade-offs.

4.8 Full worked walkthrough β€” "Design a URL shortener" 7/10

This is the most common junior/mid system-design prompt. Here's how to talk through it using the 7-step method.

Study Card #8

1. Clarify requirements. Functional: shorten a long URL β†’ short code; visiting the short code redirects. Non-functional: very read-heavy (redirects ≫ creates), low latency, highly available, links don't expire (or optionally do). Ask: expected scale? Say ~100M new URLs/month, ~10:1 read:write.

2. Estimate scale. 100M/month β‰ˆ 40 writes/sec, ~400 reads/sec before peak factors. Storage at 500 bytes per record is roughly 50 GB/month before indexes/replication. These request rates are not automatically β€œsharding scale”; start with a well-indexed primary database and add complexity only when measurements require it.

3. API.
POST /shorten { "url": "https://..." } β†’ { "short": "abc123" }
GET /abc123 β†’ redirect to the original URL

4. Data model & the key trick. A table links(id, short_code, long_url, created_at). The core question is how to generate a short unique code:

  • 7/10Take an auto-increment id and base-62 encode it (0-9,a-z,A-Z) β†’ 7 chars covers ~3.5 trillion links. Simple, collision-free, but codes are guessable/sequential.
  • 7/10Or hash the URL and take the first 7 chars, handling collisions by retrying. Non-sequential but needs collision checks.

A relational database with a unique index on short_code is a sensible start. A key-value store becomes attractive only when the access pattern and measured scale justify its operational trade-offs.

5. High-level design. Client β†’ load balancer β†’ stateless app servers β†’ database. Add Redis for demonstrably hot short codes when database load or latency requires it; do not make every design depend on a cache from day one.

6. Deep dive β€” the read path. Redirects dominate, so cache hot codes only when useful. Choose redirect semantics intentionally: a 301/308 may be cached permanently and can reduce analytics/control; a 302/307 preserves flexibility. Read replicas are a later scaling option and introduce replication lag.

7. Bottlenecks & trade-offs. At the stated scale, an identity/sequence is unlikely to be the bottleneck. At much larger multi-region write scale, discuss distributed ID generation or allocated ranges. Protect immediate read-after-write behavior, handle malicious URLs/abuse, and publish click analytics asynchronously only if analytics volume would slow redirects.

Other prompts to rehearse the same way: pastebin, rate limiter, news feed, chat app, a "like" service, a file storage service.

System design Q&A:

  • 7/10Vertical vs horizontal scaling? Vertical = bigger box (simple, capped, single point of failure); horizontal = more boxes + load balancer (scales far, needs stateless servers).
  • 8/10Why a message queue? To do slow work off the request path, decouple services, and absorb spikes β€” e.g. send confirmation emails asynchronously after checkout.
  • 7/10When NOT to use microservices? Small team, early product, unclear domain boundaries β€” the operational overhead outweighs the benefits; start with a well-structured monolith.

4.9 REST vs gRPC vs GraphQL 6/10

RESTgRPCGraphQL
6/10FormatJSON over HTTPProtobuf over HTTP/2 (binary)JSON, single endpoint
6/10Best forPublic APIs, simplicityFast internal service-to-serviceClients needing flexible/precise data
6/10StrengthsUniversal, HTTP-cache friendly, simpleCompact typed contracts, streaming, efficient internal callsClient-selected fields and graph-shaped queries
6/10WeaknessesOver/under-fetchingNot browser-native, binary to debugCaching & rate-limiting are harder

Over-fetching means an endpoint returns more than needed; under-fetching means several calls are needed. GraphQL can reduce both, but resolvers can create N+1 queries, authorization and cost controls are harder, and one client query may still trigger many backend calls.

4.10 Load balancing & consistent hashing 5/10

  • 5/10Load-balancing algorithms: round-robin (rotate), least-connections (send to the least busy), IP-hash / sticky sessions (same client β†’ same server), weighted (bigger servers get more).
  • 5/10L4 vs L7: Layer-4 balances on TCP/IP (fast, dumb); Layer-7 understands HTTP so it can route by path/host/header.
  • 5/10Consistent hashing β€” when nodes change, naive hash(key) % N remaps most keys. Ring- or rendezvous-based hashing reduces movement and is associated with Dynamo-style systems and Cassandra. Redis Cluster instead maps keys to a fixed set of hash slots; understand the goal rather than claiming every product uses the same algorithm.

4.11 Rate limiting algorithms 6/10

  • 6/10Fixed window β€” N requests per clock minute. Simple but allows bursts at boundaries.
  • 6/10Sliding window β€” smooths the boundary problem.
  • 6/10Token bucket β€” tokens refill at a steady rate; each request spends one; allows short bursts up to the bucket size. Most common in practice.
  • 6/10Leaky bucket β€” processes at a constant rate, queueing/dropping overflow.
  • 7/10ASP.NET Core implementation: register policies with AddRateLimiter and add UseRateLimiter in the pipeline. Built-in policies support fixed/sliding windows, token buckets, and concurrency limits; partition by a trustworthy user, tenant, API key, or address and return 429 with useful retry metadata.

4.12 Distributed system patterns Senior / role-dependent 6/10

Study Card #9

Idempotency 8/10

An operation that can be applied multiple times with the same intended effect. Critical with retries and at-least-once queues. Implement idempotency keys with an atomic insert/unique constraint, request fingerprint, status, and stored result; simply β€œcheck then insert” has a race condition.

CQRS (Command Query Responsibility Segregation) 6/10

Separate command and query models so each can express different concerns; they may still use the same database. Separate stores and eventual consistency are optional extensions. Use CQRS when domain/read-model complexity justifies it, not merely because a mediator library is available.

Event Sourcing 5/10

Store the authoritative sequence of domain events instead of only current state, then build projections from those events. It offers auditability and temporal reconstruction but requires event versioning, projection rebuilds, idempotency, and significant operational discipline.

Saga pattern 5/10

Coordinates a sequence of local transactions across services, using compensating actions when later steps fail. Compensation is business remediationβ€”not a perfect rollbackβ€”and both choreography and orchestration approaches have failure and observability trade-offs.

API Gateway 6/10

A single entry point in front of microservices that handles routing, auth, rate limiting, and aggregation β€” so clients don't call dozens of services directly.

Service discovery 4/10

In dynamic environments service instances come and go; a registry (Consul, Eureka, Kubernetes DNS) lets services find each other without hard-coded addresses.

Circuit breaker & bulkhead 7/10

Circuit breaker stops calling a failing dependency for a cooldown (fail fast, recover gracefully). Bulkhead isolates resources (thread pools) so one failing dependency can't sink the whole app. Polly implements both in .NET.

Outbox pattern 7/10

Write business changes and an outbox record in the same local database transaction, then publish the record asynchronously. This closes the β€œdatabase committed but message was lost” gap, but publishing remains at-least-once, so consumers still need idempotency.

4.13 Cloud / Azure concepts for .NET When the job uses Azure 7/10

Many .NET roles use Azure, but cloud-product trivia is less important than understanding the underlying compute, storage, messaging, identity, networking, and observability concepts:

  • 7/10Compute: App Service (PaaS for web apps), Azure Functions (serverless/event-driven), AKS (Kubernetes).
  • 7/10Data: Azure SQL Database (managed relational), Cosmos DB (global NoSQL), Blob Storage (files/assets).
  • 7/10Messaging: Service Bus (enterprise queues/topics), Event Grid (pub/sub), Event Hubs.
  • 7/10Security: Key Vault (store secrets, connection strings without keeping them in code), Managed Identities (resources authenticate to each other without passwords).

4.14 Second walkthrough β€” "Design a rate limiter" 6/10

Study Card #10

1. Requirements: limit each user/API-key to e.g. 100 requests/minute; must work across many app servers; low latency; fail open or closed (decide).

2. Approach: because servers are stateless and horizontally scaled, the counter must live in a shared store β€” Redis is ideal (fast, atomic operations).

3. Algorithm: token bucket or sliding-window counter. For a fixed window, increment a key such as rate:{userId}:{window} and set expiry. Use an atomic Lua script/transaction so increment and first-time expiry cannot separate; INCR alone is atomic, but a separate failed EXPIRE can leak keys.

4. Where it runs: at the API gateway or as middleware, before business logic, so rejected requests are cheap.

5. Trade-offs: fixed windows allow double bursts at boundaries β†’ use sliding window or token bucket for smoothness. Decide fail-open (allow if Redis is down β€” availability) vs fail-closed (reject β€” safety). Return 429 Too Many Requests with a Retry-After header.

4.15 System design Q&A 7/10

7/10How do you make an API idempotent?

The client sends an idempotency key (e.g. a GUID) with the request; the server records processed keys and, on a repeat, returns the stored result instead of doing the work again. GET/PUT/DELETE are naturally idempotent; POST needs the key.

7/10How do you handle a service that keeps failing?

Timeouts + retries with exponential backoff and jitter for transient errors, a circuit breaker to stop hammering it while it's down, a fallback/graceful degradation, and bulkheads so it can't exhaust shared resources.

7/10Strong vs eventual consistency?

Strong: every read sees the latest write (needed for balances/inventory) β€” costs latency/availability. Eventual: replicas converge over time; reads may be briefly stale (fine for likes, feeds, view counts) β€” scales and stays available. Choose per feature.

7/10How do you design for high availability?

No single point of failure: multiple stateless app servers behind a load balancer, DB replication with failover, multi-AZ deployment, health checks, retries/circuit breakers, and graceful degradation so a partial outage doesn't take everything down.

7/10How would you handle 10Γ— traffic overnight?

Scale horizontally (autoscaling stateless servers), add caching (Redis/CDN) to cut DB load, use read replicas, move slow work to queues, and add rate limiting to protect the core. Identify the bottleneck first (usually the database).

↑ back to top

5HTTP & Networking Fundamentals Must know 9/100/0 βœ“

Backend engineers are expected to know what happens between the browser and the server. These come up constantly.

5.1 HTTP essentials 10/10

  • 10/10Request/response model β€” client sends a method + path + headers + optional body; server replies with a status code + headers + body.
  • 10/10Methods: GET/HEAD are safe and idempotent; POST processes or creates and is not inherently idempotent; PUT creates/replaces a resource at a known URI and is idempotent; PATCH applies a partial change whose idempotency depends on the patch; DELETE is idempotent by intended effect.
  • 10/10Status families: 1xx info, 2xx success, 3xx redirect, 4xx client error, 5xx server error.
  • 10/10Headers you should know: Content-Type, Accept, Authorization, Cache-Control, ETag/If-None-Match/If-Match, Location, Retry-After, Set-Cookie, and tracing headers.
  • 10/10Idempotency & safety β€” "safe" = no side effects (GET); "idempotent" = same effect if repeated (GET/PUT/DELETE).

5.2 HTTP versions 6/10

  • 6/10HTTP/1.1 β€” persistent connections are reusable, but there is no practical multiplexing; clients often use several connections and requests can block behind earlier work.
  • 6/10HTTP/2 β€” multiplexes many requests over one connection, header compression, binary framing.
  • 6/10HTTP/3 β€” runs over QUIC (UDP), removes TCP head-of-line blocking, faster connection setup.

5.3 What happens when you type a URL and press Enter 8/10

A favorite "does he understand the stack" question:

  1. 8/10DNS lookup β€” resolve the domain to an IP (cache β†’ resolver β†’ root β†’ TLD β†’ authoritative).
  2. 8/10TCP handshake β€” SYN, SYN-ACK, ACK establishes a connection (3-way handshake).
  3. 8/10TLS handshake β€” for HTTPS, verify the certificate and establish shared session keys; asymmetric cryptography authenticates/key-agrees, then efficient symmetric encryption protects application traffic.
  4. 8/10HTTP request sent; load balancer routes it to an app server.
  5. 8/10Server processes (auth, DB, cache) and returns HTML/JSON.
  6. 8/10Browser renders; fetches more assets (often via CDN).

5.4 TCP vs UDP, TLS, cookies vs tokens 8/10

  • 8/10TCP β€” reliable, ordered, connection-based (web, DB). UDP β€” fast, connectionless, may drop packets (video, gaming, DNS).
  • 8/10HTTPS/TLS β€” provides confidentiality, integrity, and server authentication. Certificates bind a public key to a host identity; clients must validate the chain and hostname.
  • 8/10Cookies vs tokens: these are not opposites. A cookie is a browser transport/storage mechanism and can contain an opaque session ID or token. A bearer token is an authorization credential and can be sent in a header or cookie. Automatic cookie sending creates CSRF considerations; script-readable token storage creates XSS-exfiltration risk.
  • 8/10CORS β€” a browser-enforced policy controlling which origins may read cross-origin responses. It is not authentication, does not protect server-to-server endpoints, and must not replace authorization.
  • 8/10Real-time choices: WebSockets provide full-duplex communication, Server-Sent Events stream server-to-client updates over HTTP, and long polling is the fallback. SignalR abstracts transport selection and connection management.
  • 8/10Reverse proxies: TLS termination, compression, request-size limits, forwarded headers, timeouts, and client IP handling often happen before Kestrel. Trust forwarded headers only from known proxies.
8/10Difference between 401 and 403?

401 Unauthorized = not authenticated (no/invalid credentials β€” "log in"). 403 Forbidden = authenticated but not allowed to access this resource ("you can't do that").

8/10PUT vs PATCH vs POST?

POST submits a command or creates under a collection URI and is not inherently idempotent. PUT creates or replaces the representation at a known URI and is idempotent. PATCH applies a partial change; whether it is idempotent depends on the patch document, for example β€œset value” can be idempotent while β€œincrement value” is not.

↑ back to top

6Design Patterns Know selectively 7/100/0 βœ“

Reusable vocabulary for common design problems. Strategy, Factory, Adapter, Decorator, Observer, and Dependency Injection are the highest-value choices for typical .NET interviews. Do not memorize all 23 GoF patterns; explain the problem, trade-off, and why a simpler design is or is not enough.

6.1 Creational 7/10

  • 7/10Singleton β€” one shared instance (a cache, config). In .NET, prefer registering it as a DI singleton over a static class.
  • 7/10Factory / Factory Method β€” a method decides which concrete type to create, hiding construction from callers.
  • 7/10Builder β€” construct a complex object step by step (fluent APIs like StringBuilder, query builders).

6.2 Structural 6/10

  • 6/10Adapter β€” wrap an incompatible interface to make it fit (e.g. wrap a third-party SDK behind your own interface).
  • 6/10Decorator β€” add behavior by wrapping (logging/caching layer around a repository). ASP.NET middleware is decorator-like.
  • 6/10Facade β€” a simple front over a complex subsystem.
  • 6/10Proxy β€” stand-in that controls access (lazy loading, caching, access control).

6.3 Behavioral 7/10

  • 7/10Strategy β€” swap an algorithm at runtime via an interface (different payment/shipping calculators). The Open/Closed principle in action.
  • 7/10Observer β€” publish/subscribe; subscribers react to events (C# events).
  • 7/10Template Method β€” a base class defines the skeleton, subclasses fill in steps.
  • 6/10Mediator β€” objects communicate through a coordinating abstraction. Libraries such as MediatR can implement request/handler dispatch, but using a mediator does not automatically mean the architecture is CQRS.

6.4 Architectural / enterprise 8/10

  • 8/10Repository β€” can provide a domain-focused persistence boundary when it expresses meaningful aggregate operations. EF Core's DbSet and DbContext already provide repository/unit-of-work-like behavior, so a generic CRUD repository often adds indirection and blocks useful query composition.
  • 8/10Unit of Work β€” tracks a set of changes and commits them together; EF Core's DbContext already serves this role.
  • 8/10Dependency Injection β€” supply dependencies from outside (the whole basis of ASP.NET Core).
  • 8/10DTO β€” plain data objects to shape API input/output, decoupled from domain entities.

Interview tip: don't just name a pattern β€” say the problem it solves. "I'd use Strategy so I can add a new discount rule without modifying existing code (Open/Closed)." And beware over-engineering: interviewers respect knowing when not to add a pattern.

↑ back to top

7Security β€” OWASP & Hardening Must know 9/100/0 βœ“

Security questions separate juniors from mid-levels. Know the top risks and their fixes.

7.1 The classic web vulnerabilities 9/10

Study Card #11

SQL Injection 10/10

Attacker-controlled text changes the meaning of a SQL command. Fix: parameterize values, restrict database permissions, and never concatenate input into SQL. ORMs help only when you use their parameterized APIs; raw SQL remains dangerous.

// VULNERABLE
var sql = "SELECT * FROM users WHERE name = '" + input + "'";
// SAFE β€” parameterized
cmd.CommandText = "SELECT * FROM users WHERE name = @name";
cmd.Parameters.Add("@name", SqlDbType.NVarChar, 100).Value = input;

XSS (Cross-Site Scripting) 8/10

Attacker injects <script> that runs in other users' browsers. Fix: encode/escape output, use a Content-Security-Policy, and sanitize HTML. Frameworks like Razor auto-encode by default.

CSRF (Cross-Site Request Forgery) 8/10

A malicious site tricks a browser into sending an authenticated state-changing request because cookies are attached automatically. Fix: anti-forgery tokens, suitable SameSite settings, and Origin/Referer validation. Header-based bearer tokens are not automatically CSRF-safe if application code also exposes them to an attacker through XSS.

Broken authentication / access control 9/10

Weak passwords, no lockout, or missing authorization checks (a user editing another user's data by changing the id β€” IDOR). Fix: enforce authorization on every request server-side, never trust the client.

Sensitive data exposure 8/10

Fix: HTTPS everywhere, a maintained adaptive password hasher, encryption for sensitive data where appropriate, and a managed secret store rather than source control or ordinary configuration files. Never log secrets or tokens.

SSRF (Server-Side Request Forgery) 6/10

An attacker makes the server request internal or cloud-metadata URLs. Fix: allow-list destinations, resolve and validate addresses carefully, block private/link-local ranges where appropriate, restrict egress, and do not blindly fetch user-provided URLs.

Overposting / mass assignment 7/10

Binding an API request directly to an entity can let users set fields such as IsAdmin or OwnerId. Fix: use dedicated request DTOs, map only allowed fields, and authorize ownership/resource access independently.

Path traversal, command injection and unsafe deserialization 6/10

Never combine user input directly into filesystem paths, shell commands, type names, or executable serializers. Canonicalize and constrain paths, avoid shells when APIs exist, use allow-lists, and apply strict request-size/depth limits.

7.2 General hardening checklist 8/10

  • 8/10Validate input at every trust boundary with allow-lists, length/range limits, and request-size limits. Encode output for its destination context; β€œsanitize everything” is not a substitute for parameterization and output encoding.
  • 8/10Principle of least privilege for DB users, services, and tokens.
  • 8/10Keep dependencies patched (supply-chain / known-CVE risks).
  • 8/10Rate limit and add lockouts to resist brute force.
  • 8/10Don't leak stack traces or internal details in error responses.
  • 8/10For cookies use HttpOnly, Secure, and an intentional SameSite value; rotate session identifiers after privilege changes and logout.
  • 8/10Use ASP.NET Core Data Protection for protected application data and a managed secret store/managed identity for service credentials. Plan key rotation and multi-instance key sharing.
  • 8/10Log security-relevant events without logging credentials, access tokens, reset links, or sensitive personal data.
  • 8/10Hashing vs encryption: hashing is one-way (passwords); encryption is reversible with a key (data in transit/at rest). Never "encrypt" passwords β€” hash them.
8/10How do you store passwords securely?

Use ASP.NET Core Identity or another maintained password hasher configured with an adaptive salted algorithm such as PBKDF2, bcrypt, or Argon2. Never store plaintext or use a fast general-purpose hash alone. Store the algorithm/work-factor metadata so hashes can be upgraded after login.

10/10How do you prevent SQL injection?

Parameterized queries or an ORM so user input is treated as data, not code; validate input; and give the DB account least privilege. Never concatenate input into SQL strings.

↑ back to top

8DevOps β€” Git, CI/CD, Docker, Kubernetes Common in backend roles 7/100/0 βœ“

8.1 Git (you will be asked) 8/10

  • 8/10merge vs rebase: merge preserves history with a merge commit; rebase rewrites your commits on top of the target for a linear history. Don't rebase shared/public branches.
  • 8/10Common flow: branch β†’ commit β†’ push β†’ pull request β†’ review β†’ merge. Keep commits small and messages meaningful.
  • 8/10Useful commands: git stash (shelve changes), git cherry-pick (grab one commit), git revert (undo a commit safely), git reset (move the branch pointer β€” careful).
  • 8/10Resolving conflicts β€” Git marks both versions; you pick/merge the correct result and commit.

8.2 CI/CD 7/10

  • 7/10CI (Continuous Integration) β€” every push builds and runs tests automatically, catching breakage early.
  • 7/10CD (Continuous Delivery/Deployment) β€” automatically ship passing builds to staging/production.
  • 7/10Deployment strategies: blue-green (two environments, switch traffic), canary (roll out to a small % first), rolling (replace instances gradually). All aim for zero-downtime and easy rollback.
  • 7/10A useful pipeline: restore with a locked dependency graph β†’ compile with warnings treated intentionally β†’ unit/integration tests β†’ security/license scans β†’ build an immutable artifact/image β†’ deploy progressively β†’ smoke/health checks β†’ observe β†’ roll back if needed.
  • 7/10Database changes: use backward-compatible expand/migrate/contract steps so old and new app versions can overlap during a rolling deployment.

8.3 Docker & Kubernetes 7/10

  • 7/10Container β€” packages the app and runtime dependencies into an isolated process image. It improves repeatability but does not by itself solve configuration, state, networking, or observability.
  • 7/10Image vs container β€” an image is the immutable template; a container is a running instance of it.
  • 7/10Docker practices: use multi-stage builds, small supported runtime images, a non-root user, immutable tags/digests, environment/secret injection, and a correct ENTRYPOINT. Write logs to stdout/stderr and handle SIGTERM for graceful shutdown.
  • 4/10Kubernetes Role-dependent β€” orchestrates containers: scheduling, scaling, replacement, service discovery, and rolling updates. Know Pod, Deployment, Service, Ingress/Gateway, ConfigMap/Secret, resource requests/limits, and liveness/readiness/startup probes if the job uses it.
  • 7/1012-Factor App β€” config in the environment, stateless processes, logs as streams, dev/prod parity β€” principles for cloud-native services.
  • 7/10Infrastructure as Code: tools such as Bicep, Terraform, or Pulumi make environments reviewable and repeatable. Keep application configuration separate from secrets.
7/10VM vs container?

A VM virtualizes hardware and runs a full guest OS (heavy, slow to start). A container virtualizes the OS and shares the host kernel (lightweight, starts in ms). Containers give faster, denser deployments; VMs give stronger isolation.

7/10merge vs rebase β€” which and when?

Merge to integrate a finished branch while keeping true history (safe for shared branches). Rebase to tidy your local feature branch into a clean linear history before opening a PR. Never rebase commits others have already pulled.

↑ back to top

9Practical Interview Rounds Must prepare 10/100/0 βœ“

Many .NET employers care more about production judgment than puzzle difficulty. Prepare for these formats explicitly.

9.1 Project deep-dive 10/10

Choose one project you know well and prepare a 5–10 minute explanation:

  1. 10/10The user/business problem and your exact responsibility.
  2. 10/10The request flow: client β†’ API β†’ domain/service β†’ database/external dependency.
  3. 10/10Why you chose the architecture and data model; what alternatives you rejected.
  4. 10/10Authentication, authorization, validation, error handling, logging, and tests.
  5. 10/10One production bug or performance issue, how you diagnosed it, and the measured result.
  6. 10/10What you would change with more time. Honest trade-offs are stronger than claiming perfection.

9.2 Debugging and troubleshooting 9/10

Study Card #12

Use a disciplined sequence 9/10

  1. 9/10Define impact: who is affected, since when, which endpoints/regions/versions, and whether data integrity is at risk.
  2. 9/10Stabilize: roll back, disable a feature flag, shed load, or fail over if the incident is active.
  3. 9/10Gather evidence: deployment history, structured logs, traces, metrics, exception details, dependency health, database waits and query plans. On a live .NET process, dotnet-counters, dotnet-trace, and dotnet-dump/dotnet-gcdump capture metrics, traces, and heap dumps.
  4. 9/10Narrow the fault: application vs database vs network vs dependency; compare healthy and unhealthy requests; reproduce safely.
  5. 9/10Fix and prove: add a focused regression test, deploy gradually, observe the relevant SLI, and document prevention.

Common scenarios 9/10

  • 9/10High latency: inspect p95/p99, traces, ThreadPool/CPU, connection pools, slow SQL, N+1 queries, locks, downstream timeouts, payload size, and GC pressure.
  • 9/10High CPU: profile before optimizing; look for tight loops, expensive serialization/regex, excessive parallelism, retry storms, and hot allocations.
  • 9/10Memory growth: distinguish managed heap, native memory, cache growth, retained event handlers/statics, unbounded queues, and large-object allocations; compare heap snapshots.
  • 9/10Intermittent 500s: correlate by trace ID, preserve exception context, inspect recent changes and dependency failures, and avoid β€œcatch Exception and return 200” fallbacks.

9.3 Code-review exercise 8/10

Review in this order: correctness and edge cases β†’ security/authorization β†’ data consistency and transactions β†’ async/cancellation β†’ SQL/EF query shape β†’ error handling/observability β†’ tests β†’ readability. Comment on high-impact issues, explain the consequence, and propose a concrete fix; do not drown the author in style preferences.

9.4 Take-home or pair-programming API 9/10

  • 9/10Clarify requirements and make the smallest complete design; avoid unnecessary microservices, generic repositories, or patterns.
  • 9/10Use request/response DTOs, validation, correct status codes, ProblemDetails, cancellation tokens, and async I/O.
  • 9/10Use migrations, constraints, deliberate EF queries, and tests that cover behavior and one realistic integration path.
  • 9/10Add a short README explaining how to run it, assumptions, trade-offs, and what you would improveβ€”not a novel.
  • 9/10Before finishing, run tests, inspect generated SQL/logs, try invalid/unauthorized/concurrent requests, and remove secrets and debug artifacts.

9.5 Questions to ask the interviewer 8/10

  • 8/10What would success look like in the first 90 days?
  • 8/10How are architecture decisions made and reviewed?
  • 8/10What are the largest reliability or delivery challenges today?
  • 8/10How do you test, deploy, observe, and handle on-call incidents?
  • 8/10Which .NET versions and cloud/data technologies are actually used?

↑ back to top

🎯100+ Rapid-Fire Question Bank 9/100/0 βœ“

Cover the answer, say it out loud, then check. This is a revision toolβ€”not a substitute for coding, SQL practice, project explanations, and mock interviews.

Algorithms & data structures 7/10

  1. 9/10Big-O of hash lookup? O(1) average, O(n) worst.
  2. 9/10Big-O of binary search? O(log n).
  3. 6/10When is quicksort O(nΒ²)? When pivot choices are consistently poorβ€”for example, always choosing the first item on already sorted input. Randomized/introspective implementations avoid this simple case.
  4. 5/10Which sorts are stable? Merge sort, insertion sort.
  5. 8/10Array vs linked list trade-off? Array: O(1) index; list: O(1) insert at node.
  6. 8/10Stack vs queue? LIFO vs FIFO.
  7. 7/10BFS data structure? Queue. DFS? Stack/recursion.
  8. 5/10Shortest path unweighted? BFS. Weighted? Dijkstra.
  9. 6/10Detect a cycle in a list? Fast/slow pointers.
  10. 6/10What is memoization? Caching subproblem results in recursion.
  11. 5/10DP vs greedy? DP explores optimal substructure; greedy takes local best.
  12. 6/10In-order traversal of a BST yields? Sorted order.
  13. 6/10Heap gives you? Min/max in O(1), insert/remove O(log n).
  14. 7/10Two-pointer use case? Sorted-array pair sums, palindromes.
  15. 7/10Sliding window use case? Longest/shortest contiguous subarray.
  16. 9/10Hash set solves? Dedup / "seen before" in O(1).
  17. 5/10Topological sort needs? A DAG (no cycles).
  18. 7/10Space complexity of recursion depth d? O(d) stack.

C# / .NET 10/10

  1. 10/10Value vs reference type? Assignment copies the value data vs copies a reference to the same object; storage location is not the definition.
  2. 8/10Why is string immutable? Its value cannot change after creation, enabling safe sharing, stable hashing, and interning of eligible strings such as literals.
  3. 7/10StringBuilder when? Many concatenations in a loop.
  4. 9/10IEnumerable vs IQueryable? IEnumerable<T> enumerates values using .NET operators; IQueryable<T> builds expression trees a provider may translate, commonly to SQL.
  5. 9/10Deferred execution? LINQ runs when enumerated.
  6. 10/10Task vs Thread? A Task represents an operation/result; it may have no dedicated thread. A Thread is an OS execution resource.
  7. 10/10Why not block on async? It wastes ThreadPool threads and can cause starvation; classic context deadlocks are not the default ASP.NET Core explanation.
  8. 10/10DI lifetimes? Transient, scoped, singleton.
  9. 9/10DbContext lifetime? Scoped; not thread-safe.
  10. 9/10abstract class vs interface? Shared base identity/state vs a multi-implementable contract; modern interfaces may include default members.
  11. 8/10override vs new? Override = runtime polymorphic dispatch; new = hides the base method, chosen by the reference's compile-time type.
  12. 8/10protected internal vs private protected? Subclasses OR same assembly vs subclasses AND same assembly.
  13. 6/10What does sealed do? Blocks inheritance (class) or further overriding (member).
  14. 8/10What is boxing? Copying a value type into an object or interface representation, normally allocating a boxed object.
  15. 7/10const vs readonly? Compile-time vs runtime.
  16. 9/10record vs class? Records provide value-based equality by default; they are not automatically immutable.
  17. 7/10yield return? Lazy iterator.
  18. 8/10What is a closure? Lambda capturing outer variables.
  19. 8/10GC generations? 0 (young), 1, 2 (old), LOH.
  20. 7/10Workstation vs Server GC? Server GC (ASP.NET Core default) trades memory for throughput with per-core heaps; Workstation favors footprint.
  21. 9/10GC vs Dispose? GC reclaims managed memory; Dispose releases scarce resources deterministically.
  22. 9/10What does using guarantee? Dispose runs even on exception.
  23. 10/10Middleware order matters? Yesβ€”exception handling early; routing before conventional authentication/authorization; authentication before authorization.
  24. 8/10Func vs Action? Returns a value vs void.
  25. 8/10What do CLR, IL, and JIT do? C# compiles to IL/metadata; CLR loads/manages it; JIT compiles executed methods to native code.
  26. 9/10throw; vs throw ex;? throw; preserves the original stack trace.
  27. 9/10Why avoid async void? Callers cannot await completion or observe exceptions; reserve it for event handlers.
  28. 9/10When use Task.WhenAll? For independent async work, with bounded fan-out.
  29. 10/10What is cancellation? Cooperative signaling through CancellationToken; propagate it to I/O.
  30. 9/10Why IHttpClientFactory? Handler/connection reuse, DNS refresh, typed configuration, and resilience.
  31. 8/10What is ProblemDetails? A standardized machine-readable API error shape.
  32. 10/10Authentication vs authorization? Establish identity vs decide permission.
  33. 8/10Controllers vs Minimal APIs? Both are valid; choose based on conventions and complexity.
  34. 8/10How test the real ASP.NET Core pipeline? WebApplicationFactory<Program> integration tests.
  35. 5/10What are keyed DI services? Named/keyed registrations for choosing among multiple implementations of one service contract.
  36. 7/10How do you enable built-in rate limiting? Register policies with AddRateLimiter, call UseRateLimiter, and partition by a trustworthy client identity.
  37. 7/10Output caching vs data caching? Output caching reuses a complete HTTP response; data caching reuses an internal value used to build a response.
  38. 5/10What is System.Threading.Channels for? Bounded asynchronous producer/consumer queues inside one process, including backpressure.

Databases 9/10

  1. 9/10WHERE vs HAVING? Rows before grouping vs groups after.
  2. 10/10INNER vs LEFT JOIN? Matches only vs all-left + NULLs.
  3. 10/10What is an index? An access structure, often a B-tree, that can reduce pages scanned; benefit depends on selectivity and query shape.
  4. 9/10Index downside? Slower writes, storage.
  5. 8/10Clustered vs non-clustered in SQL Server? Rows are organized by one clustered key vs separate index structures that locate rows.
  6. 10/10ACID? Atomicity, Consistency, Isolation, Durability.
  7. 10/10N+1 problem & fix? One parent query plus per-row queries; prefer projection or deliberate eager/split loading.
  8. 8/10Normalization goal? Remove redundancy.
  9. 7/10When denormalize? Read-heavy performance.
  10. 7/10SQL vs NoSQL? Choose by data relationships, invariants, query/access patterns, consistency, and operationsβ€”not a slogan about scale.
  11. 8/10Window function vs GROUP BY? Keeps rows vs collapses them.
  12. 8/10Optimistic vs pessimistic locking? Version-check vs lock upfront.
  13. 8/10What causes a deadlock? Opposite lock ordering.
  14. 9/10Transaction isolation levels? Read Uncommitted β†’ Serializable.
  15. 6/10EXISTS vs IN? Choose semantics first; modern optimizers may produce the same plan, while NULL behavior can differ.
  16. 7/10Read replica purpose? Scale reads; eventual consistency.
  17. 6/10Sharding? Split data across DBs by key.
  18. 10/10Fix a slow query? Index, plan, select fewer cols, avoid N+1.
  19. 9/10When use AsNoTracking? Read-only entity queries that do not need change tracking; projection may be better.
  20. 6/10When consider DbContext pooling? After measuring context setup overhead in a high-throughput service; pooled contexts must not retain request-specific mutable state.
  21. 10/10When does an EF query execute? On enumeration or terminal operations such as ToListAsync/FirstAsync.
  22. 7/10Bulk update without loading entities? ExecuteUpdateAsync/ExecuteDeleteAsync (EF Core 7+); they bypass change tracking and run immediately.
  23. 9/10Why use projection? Fetch only required columns and avoid unnecessary entities/tracking.
  24. 8/10What is cartesian explosion? Large duplicated result sets caused by joining multiple collection navigations.
  25. 8/10What is SARGability? Writing predicates an index can seek on.
  26. 8/10NULL = NULL? Unknown, not true; use IS NULL.
  27. 7/10UNION vs UNION ALL? Deduplicates vs keeps all rows and is usually cheaper.

System design, HTTP & security 8/10

  1. 8/10Stateless server benefit? Any server handles any request β†’ scale.
  2. 7/10Vertical vs horizontal scaling? Bigger box vs more boxes.
  3. 8/10Cache-aside pattern? Check cache β†’ miss β†’ DB β†’ populate.
  4. 8/10Hard part of caching? Invalidation / staleness.
  5. 8/10Why a message queue? Async work, decoupling, spike absorption.
  6. 8/10At-least-once delivery needs? Idempotent consumers.
  7. 9/10What must an API validate in a JWT? Allowed algorithm, signature, issuer, audience, lifetime, and required claims.
  8. 10/10401 vs 403? Not authenticated vs not allowed.
  9. 10/10200 vs 201 vs 204? OK vs Created vs No Content.
  10. 9/10Which HTTP methods are idempotent by specification? GET, HEAD, PUT, DELETE, OPTIONS, and TRACE; POST and PATCH are not guaranteed to be idempotent.
  11. 7/10CAP theorem? During a network partition, an operation cannot guarantee both linearizable consistency and a non-error response from every node.
  12. 7/10Strong vs eventual consistency? Latest read vs converges over time.
  13. 8/10TCP vs UDP? Reliable/ordered vs fast/lossy.
  14. 8/10What is CORS? Browser cross-origin permission via headers.
  15. 5/10Consistent hashing solves? Minimal remap when nodes change.
  16. 7/10Circuit breaker does? Stops calling a failing dependency.
  17. 5/10Load balancer algorithms? Round-robin, least-conn, IP-hash.
  18. 8/10Monolith vs microservices? Simple vs independently scalable+complex.
  19. 10/10Prevent SQL injection? Parameterized queries.
  20. 8/10Prevent XSS? Encode output, CSP.
  21. 10/10Store passwords how? Use a maintained adaptive salted password hasher such as ASP.NET Core Identityβ€”not custom crypto.
  22. 8/10Hashing vs encryption? One-way vs reversible with key.
  23. 6/10Blue-green deployment? Two envs, switch traffic, easy rollback.
  24. 7/10Container vs VM? Shares kernel (light) vs full OS (heavy).
  25. 6/10Rate limiter algorithm? Token bucket (allows bursts).
  26. 9/10OAuth 2.0 vs OIDC? Delegated authorization vs authentication/identity on top of OAuth.
  27. 7/10Why PKCE? Protect authorization-code flow for public clients from intercepted codes.
  28. 8/10Cookie security flags? HttpOnly, Secure, and intentional SameSite.
  29. 8/10When is CSRF relevant? When credentials such as cookies are attached automatically to cross-site requests.
  30. 6/10What is SSRF? Attacker causes the server to request restricted/internal destinations.
  31. 7/10What is a cache stampede? Many misses rebuild the same value simultaneously.
  32. 7/10SLI vs SLO vs SLA? Measurement vs target vs external commitment.
  33. 6/10RTO vs RPO? Recovery-time target vs acceptable data-loss window.
  34. 7/10Why the outbox pattern? Atomically save business data and a message-to-publish in one database transaction.
  35. 8/10What is backpressure? Limiting producers/concurrency so slow consumers do not exhaust resources.

Practical engineering 8/10

  1. 9/10First step in an incident? Define impact and stabilize the system before deep diagnosis.
  2. 9/10How investigate latency? Start with p95/p99 and traces, then check ThreadPool/CPU, SQL, pools, dependencies, payloads, and GC.
  3. 8/10How investigate memory growth? Measure managed/native memory and compare heap snapshots for retained roots and unbounded structures.
  4. 8/10Code-review priority? Correctness/security/data consistency before style.
  5. 9/10What makes a strong take-home? Small complete design, correct contracts, tests, migrations, errors, security, and documented trade-offs.
  6. 10/10What should a project story contain? Problem, your role, architecture, trade-offs, failure/debugging story, result, and improvements.

↑ back to top

β˜…Behavioral Interviews (with sample answers) Must prepare 9/100/0 βœ“

Technical skill gets you shortlisted; behavioral rounds often decide the offer and your level/salary. Use the STAR method: Situation (context), Task (your goal), Action (what you did), Result (measurable outcome). Keep it 60–90 seconds, first-person, and end with the result.

Prepare 5–6 reusable stories: a hard bug you fixed Β· a conflict with a teammate Β· a mistake/missed deadline and what you learned Β· something you're proud of building Β· learning a new technology fast Β· improving performance or reliability.

9/10Sample: "Tell me about a challenging bug."

(STAR) "On our payments service (S), users occasionally saw duplicate charges (T). I added correlation-ID logging and traced it to retries hitting a non-idempotent endpoint (A β€” investigation). I introduced an idempotency key stored in Redis so repeated requests were deduplicated, and added a regression test. Duplicate charges dropped to zero and we shipped the fix within two days (R)."

9/10Sample: "Tell me about a conflict with a teammate."

Focus on listening, data, and outcome, never on blame: "We disagreed on SQL vs NoSQL for a new service. Rather than argue, I proposed we each write down our requirements; once we listed them, it was clear the data was highly relational, so we chose Postgres β€” and my teammate agreed because the decision was based on our actual needs, not opinion."

Common questions to rehearse: "Tell me about yourself" (a 2-minute pitch: present role β†’ relevant past β†’ why this role), "Why this company?", "Biggest weakness?" (a real one + how you're improving it), "Why leaving?". Always prepare questions for them β€” about the team, tech stack, on-call, and how success is measured. It signals genuine interest.

β˜…How to behave during a live coding interview Must practice 8/100/0 βœ“

Live Coding Loop Checklist

The process is graded as much as the final code. Follow this loop out loud:

  1. 8/10Clarify β€” restate the problem; ask about input size, types, edge cases, and constraints before writing anything.
  2. 8/10Think out loud β€” narrate your reasoning. Silence is the #1 reason strong coders fail.
  3. 8/10Brute force first β€” propose a naive solution and state its complexity, so you have something working.
  4. 8/10Optimize β€” "can a hash map, two pointers, or sorting reduce this?" Explain the improvement.
  5. 8/10Code cleanly β€” meaningful names, small steps; handle empty/null/duplicate edge cases.
  6. 8/10Test β€” trace through a normal example and an edge case, out loud.
  7. 8/10State final complexity β€” time and space.
  8. 8/10If stuck β€” reason toward it out loud; asking for a hint is normal and better than freezing.

Red flags to avoid: going silent, coding before you understand the problem, ignoring edge cases, giving up with "I don't know", and arguing with the interviewer instead of engaging with their hint.

πŸ“…4-Week Study Plan 9/100/0 βœ“

Assume roughly 1–2 focused hours per day. If the job description emphasizes algorithms, move extra time into DSA; otherwise keep .NET, SQL, API design, and practical engineering at the center.

Study Card #13

Week 1 β€” C#, CLR, async, HTTP 10/10

  • 10/10Types, collections, generics, equality, LINQ, exceptions, nullable references, CLR/IL/JIT, GC basics.
  • 10/10Async I/O vs CPU work, cancellation, Task.WhenAll, thread safety, and common async mistakes.
  • 10/10HTTP methods/status codes, TLS/DNS basics, cookies/tokens/CORS.
  • 10/10One or two targeted coding problems per day: arrays, dictionaries, strings, stacks/queues, binary search.

Week 2 β€” ASP.NET Core, EF Core, SQL 10/10

  • 9/10Build or revise one small API: DI, middleware, validation, auth policies, ProblemDetails, OpenAPI, logging, cancellation.
  • 10/10EF Core tracking, projection, loading, migrations, concurrency, transactions, N+1, split queries.
  • 10/10Write SQL daily: joins, aggregation, window functions, constraints, indexes, isolation, execution plans, keyset pagination.

Week 3 β€” Testing, security, operations, design 9/10

  • 9/10Unit tests plus one WebApplicationFactory integration test against a realistic database.
  • 8/10SQL injection, XSS, CSRF, SSRF, overposting, OAuth/OIDC, secure cookies, secret handling.
  • 9/10Docker/CI/CD, health checks, OpenTelemetry, retries/timeouts, caching, queues, idempotency.
  • 9/10Practice one API design and one system-design walkthrough with explicit trade-offs.

Week 4 β€” Interview simulation and weak spots 10/10

  • 10/10Rehearse a project deep-dive, a debugging scenario, a code review, and 5–6 STAR stories.
  • 10/10Do 2–3 timed mocks: C#/API questions, SQL, coding, and role-appropriate system design.
  • 10/10Review the target company's stack and job description; deepen Azure, Kubernetes, algorithms, or messaging only where relevant.

Daily loop: learn one concept β†’ explain it aloud without notes β†’ implement or query something small β†’ answer one follow-up/trade-off question β†’ record mistakes for spaced review. Passive reading alone does not prepare you for an interview.

⚑Quick Cheat-Sheet 10/100/0 βœ“

Study Card #14
  • 10/10C#/.NET: copy semantics Β· generics/equality Β· LINQ execution Β· exceptions Β· CLR/JIT/GC Β· async I/O, cancellation, bounded concurrency.
  • 9/10ASP.NET Core: Kestrel/pipeline Β· DI lifetimes Β· DTO validation Β· auth policies Β· ProblemDetails Β· OpenAPI Β· HttpClient reuse Β· observability.
  • 10/10EF Core/SQL: projection and deliberate tracking/loading Β· generated SQL Β· joins/indexes/plans Β· ACID/isolation Β· optimistic concurrency Β· keyset pagination.
  • 8/10Security: parameterization Β· output encoding Β· CSRF/SSRF/overposting Β· OIDC/JWT validation Β· secure cookies/secrets Β· least privilege.
  • 10/10System design: requirements β†’ scale β†’ API/data model β†’ simple baseline β†’ failures/consistency β†’ cache/queue only with a reason β†’ observability/recovery.
  • 10/10Interview behavior: clarify Β· think aloud Β· test edge cases Β· discuss trade-offs Β· use evidence when debugging Β· prepare project and STAR stories.

Good luck β€” consistency beats intensity. A little every day compounds fast. You've got this. πŸš€

No items match the current filter

Try switching the filter back to All or clearing your search query.