Quick software engineering explainers for things you should've googled by now

Join the newsletter →
Classic pagination bug: a product search feels instant on the first few pages, then gets slower the deeper it goes. A few hundred pages in, response times stretch into seconds and CPU usage goes up. OFFSET is the culprit, and the fix is a one-line change to the query.
2
5
42
23,931
The Happy Path retweeted
Node.js handles thousands of concurrent requests with one thread and an event loop. Pretty efficient. But... is that always the case? Here's how you can stall a Node.js server: give it a CPU-heavy task. While one callback renders a PDF, every other request waits.
1
85
Node.js executes JavaScript on a single thread. So how does it handle thousands of concurrent requests? Database queries, network calls and file reads are handed off to the OS and libuv. The event loop executes each callback once its result is ready.
2
1
5
294
Rate limiting and throttling often get used as synonyms. AWS API Gateway even calls its 429 errors "throttling". Strictly speaking, a rate limiter rejects requests over the limit, and a throttler queues them and handles them later.
2
1
4
227
Just crossed 3,000 followers 🤯 Thank you all for your continued support. To mark it, The Happy Path now has a newsletter: software engineering explainers by email, with room to go deeper than a single X post allows. newsletter.thehappypath.dev
4
189
C: a is [1, 3] and b is [1, 2]. a = b = [] binds both names to one list, and a.append(1) adds 1 to it. b + [2] builds a new list and points b at it. a.append(3) only reaches the original list.
Python list aliasing, in four lines. a = b = [] a.append(1) b = b + [2] a.append(3) A) a = [1, 2, 3], b = [1, 2, 3] B) a = [1, 3], b = [2] C) a = [1, 3], b = [1, 2] What do you expect a and b to be?
8
833
Python list aliasing, in four lines. a = b = [] a.append(1) b = b + [2] a.append(3) A) a = [1, 2, 3], b = [1, 2, 3] B) a = [1, 3], b = [2] C) a = [1, 3], b = [1, 2] What do you expect a and b to be?
2
7
1,252
How can two machines share a secret key that doesn't travel over the network? Diffie-Hellman. Each side keeps a private number and sends a value derived from it. The value each side receives, combined with its own private number, produces the shared key.
1
10
486
B, DENSE_RANK. Tied rows share a position, and the next row takes the next number: 1, 2, 2, 3. RANK leaves a gap after the tie (1, 2, 2, 4). ROW_NUMBER gives every row its own number (1, 2, 3, 4).
This SQL query ranks four salaries with one tie and returns pos 1, 2, 2, 3. SELECT name, salary, ____() OVER (ORDER BY salary DESC) AS pos FROM employees; A) RANK B) DENSE_RANK C) ROW_NUMBER Which window function would you write?
4
370
This SQL query ranks four salaries with one tie and returns pos 1, 2, 2, 3. SELECT name, salary, ____() OVER (ORDER BY salary DESC) AS pos FROM employees; A) RANK B) DENSE_RANK C) ROW_NUMBER Which window function would you write?
1
1
4
610
A, weather & rivers. Embeddings place text by meaning. Here "river" and "flooded" make "bank" the riverside. Its nearest neighbours are the flood sentences, even though the banking ones share the word "bank".
A vector database turns every sentence into an embedding: a point in space, where similar text sits close together. Where does this one land? "The bank of the river flooded overnight." A) Weather & rivers B) Banking C) Cooking
3
282
A vector database turns every sentence into an embedding: a point in space, where similar text sits close together. Where does this one land? "The bank of the river flooded overnight." A) Weather & rivers B) Banking C) Cooking
5
551
B, neither applied. That's atomicity: a transaction is applied in full or not at all. On restart, recovery keeps only committed transactions. This one had not reached COMMIT.
You're moving 100 from alice to bob in one ACID transaction: debit, credit, COMMIT. The server crashes after the debit, before COMMIT. After restart, what's in the database? A) alice debited, bob unchanged B) neither applied C) both applied D) depends on the isolation level
2
243
You're moving 100 from alice to bob in one ACID transaction: debit, credit, COMMIT. The server crashes after the debit, before COMMIT. After restart, what's in the database? A) alice debited, bob unchanged B) neither applied C) both applied D) depends on the isolation level
1
1
1
386
C, both: the list changes and a TypeError is raised. += on a list extends it in place first. Then the result is written back into t[0], and tuples don't support item assignment.
A Python tuple can contain a mutable list. Here, += is applied to that list. t = ([1, 2],) t[0] += [3] A) TypeError B) t becomes ([1, 2, 3],) C) Both What do you think happens?
1
181
A Python tuple can contain a mutable list. Here, += is applied to that list. t = ([1, 2],) t[0] += [3] A) TypeError B) t becomes ([1, 2, 3],) C) Both What do you think happens?
2
1
4
404
NoneTypeError is the fake. Calling a method on None raises AttributeError: 'NoneType' object has no attribute 'x'.
Four Python exceptions. Three are real. - StopIteration - MemoryError - NoneTypeError - RecursionError Can you spot the fake one?
1
2
226
Four Python exceptions. Three are real. - StopIteration - MemoryError - NoneTypeError - RecursionError Can you spot the fake one?
1
3
467
B. Logically, WHERE is evaluated before SELECT, and the alias doubled only exists from SELECT on. ORDER BY is evaluated after SELECT and can use it.
PostgreSQL. A query that filters on its own alias. SELECT price * 2 AS doubled FROM items WHERE doubled > 10 A) returns the matching rows B) error: column "doubled" does not exist Which one do you get?
7
269
PostgreSQL. A query that filters on its own alias. SELECT price * 2 AS doubled FROM items WHERE doubled > 10 A) returns the matching rows B) error: column "doubled" does not exist Which one do you get?
3
401