the notes I wish I had before I needed them

Cheatsheet

Quick-reference notes across the stack I actually work in. Pick a topic, or search for a term across all of them.

Go

nil slice vs empty slice

both len()==0, but nil slice serializes to `null` in JSON while [] serializes to an empty array — matters for API contracts.

defer in a loop

defers run at function return, not loop-iteration end — wrap the loop body in its own function if you're deferring per-iteration cleanup.

goroutine leaks

a goroutine blocked on an unbuffered channel with no reader/writer on the other end never gets garbage collected — always give goroutines a cancellation path via context.

error wrapping

use fmt.Errorf("...: %w", err) instead of %v so errors.Is / errors.As can still unwrap the chain.

context cancellation

propagate context.Context as the first argument through call chains and check ctx.Err() in long-running loops, don't just pass it through decoratively.

Python

mutable default args

def f(x=[]) reuses the same list across calls — default to None and initialize inside the function body instead.

GIL

the GIL means threading doesn't help CPU-bound work — use multiprocessing or a language extension for CPU-bound parallelism, threading is fine for I/O-bound work.

generators vs lists

prefer a generator when you only iterate once over a large sequence — trades a bit of speed for constant memory instead of O(n).

virtual environments

always isolate project dependencies (venv, uv, poetry) — global installs are how 'works on my machine' is born.

Java

equals() and hashCode()

override both together, never just one — breaking the contract silently corrupts HashMap/HashSet behavior.

checked exceptions

reserve them for recoverable conditions the caller should handle; everything else should be an unchecked RuntimeException, or you end up with throws clauses infecting every signature.

streams vs loops

streams read well for transformations/filtering, but a plain for-loop is often faster and clearer for simple iteration — don't stream just to look modern.

JVM heap flags

-Xms and -Xmx set equal avoids heap resize pauses in production; -XX:+HeapDumpOnOutOfMemoryError earns its keep the first time you need it.

System Design

CAP theorem

during a network partition you pick consistency or availability — most systems actually want 'eventual consistency, mostly available' rather than a hard CP/AP label.

idempotency keys

any endpoint that can be retried (payments, order creation) needs a client-supplied idempotency key, or retries create duplicates.

caching layers

cache invalidation is the hard part, not the caching — decide your invalidation strategy (TTL, write-through, event-based) before you decide your cache technology.

back-pressure

a fast producer and a slow consumer without back-pressure just moves the queue into your process's memory until it OOMs — bound your queues.

read vs write scaling

most systems are read-heavy — reach for read replicas and caching before you reach for sharding, sharding is the expensive last resort.

Microservices

service boundaries

split by business domain/data ownership, not by technical layer — 'user service' not 'database service'.

distributed transactions

avoid two-phase commit across services — use the saga pattern (a sequence of local transactions with compensating actions) instead.

circuit breakers

wrap calls to downstream services so a struggling dependency fails fast instead of piling up threads/connections and taking you down with it.

API versioning

version from day one (even if it's just /v1/) — retrofitting versioning onto a live API is far more painful than starting with it.

correlation IDs

generate one at the edge and pass it through every downstream call and log line — it's the only way to reconstruct a request's path during an incident.

ELK Stack

structured logging

log JSON with consistent field names from day one — free-text logs are unsearchable at any real scale.

index lifecycle management

set retention/rollover policies before you need them — an unmanaged index growing forever is how Elasticsearch clusters go red during an incident.

high-cardinality fields

avoid indexing fields like raw user IDs or timestamps as `keyword` at high cardinality — it bloats the index and slows aggregations.

Kibana saved searches

save your incident-response queries in advance — writing a KQL query from scratch during an outage is the wrong time to learn syntax.

Data Structures & Algorithms

hash map vs tree map

hash map gives O(1) average lookup with no ordering; tree map (red-black tree) gives O(log n) lookup but keeps sorted order — pick based on whether you need range queries.

two-pointer / sliding window

reach for these on sorted-array or substring problems before reaching for nested loops — turns many O(n²) brute forces into O(n).

recursion vs iteration

recursion reads cleaner for tree/graph traversal, but watch stack depth on deep/unbalanced structures — convert to iterative with an explicit stack if that's a risk.

Big-O gut check

if input size is ~10^5 or more, anything above O(n log n) is probably going to time out — that constraint alone rules out a lot of brute-force options fast.

Options Trading

Delta

your directional exposure, and a rough proxy for probability of finishing in-the-money — a 0.30 delta option is roughly a 30% chance of expiring ITM.

Theta

time decay, and it's not linear — it accelerates hard in the final 30-45 days to expiration. Sellers want that; buyers are fighting it every single day.

Vega / IV crush

options are priced on implied volatility, not just the stock price. Even a correct directional call can lose value if IV collapses after an event like earnings — 'right on direction, wrong on IV' is a very expensive lesson.

Covered call vs cash-secured put

both are the same risk profile with different entry points — pick based on whether you'd rather already own the stock or be waiting to.

Iron condor

a defined-risk, range-bound premium-selling strategy — sell a call spread and a put spread around the current price. Works when the stock goes nowhere, which is most of the time.

Position sizing

risk a fixed, small percentage of account equity per trade, not a fixed number of contracts — position size should shrink as volatility (and therefore risk per contract) rises.

Assignment risk

short ITM options can be assigned early, especially calls right before an ex-dividend date — know your assignment risk before you're surprised by it Monday morning.