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.