fishmemory
Guide reviews: 2026-09-23 – 2026-10-07

Anti-amnesia for software engineers

You knew this.
Let's bring it back.

A symptom-first field guide for engineers whose instincts got a little rusty while AI wrote the happy path. No shame. No 40-hour course. Just the mental models you need when production gets weird.

THE FIELD GUIDE

What are you trying to remember?

24 of 24 guides

Mobile 8 min

A long list loads and scrolls slowly

“Normal accounts feel fine. Power users with years of history report blank frames and lag.”

Separate server latency, payload cost, JavaScript work, rendering, and memory before reaching for a new list library.

Mobile 6 min

A broken mobile release is already in production

“A severe bug shipped, but App Store and Play Store review may delay a replacement binary.”

Mitigate remotely first, then use a compatible over-the-air update when the defect is in JavaScript or assets.

System design 10 min

WebSockets disconnect, duplicate, or lose events

“The live UI looks correct most of the time, but reconnects produce gaps, duplicates, stale balances, or event storms.”

A socket provides freshness, not durable truth. Design reconnect, replay, ordering, idempotency, and snapshot recovery explicitly.

  • ECONNRESETNode.js system errors
  • 1006WebSocket close codes · RFC 6455
Backend 7 min

A retry creates two payments

“The client timed out, retried the request, and both attempts reached the payment provider.”

Treat retries as normal and bind all repetitions of one user intention to one durable payment attempt.

  • 23505PostgreSQL SQLSTATE
  • ECONNRESETNode.js system errors
Frontend 9 min

Optimistic UI lies about money

“A transaction appears successful, disappears, or makes funds spendable before authoritative state catches up.”

Keep intent, execution, and authoritative reads distinct. Optimism may bridge latency but cannot invent financial facts.

Architecture 7 min

The team wants microservices too early

“A young product has unclear boundaries but is accumulating queues, network calls, deployments, and distributed transactions.”

Start with strong module boundaries inside one deployable system, then extract only where operational evidence justifies it.

Backend 6 min

An endpoint gets slower as results grow

“The endpoint performs acceptably for ten records but collapses for hundreds, while database query count rises with result count.”

Recognize N+1 access: one query loads the collection and another query runs for every item.

  • 57014PostgreSQL SQLSTATE
Web3 9 min

A Web3 payment feels like developer tooling

“Users must understand networks, gas, token allowances, hashes, and finality before making an ordinary payment.”

Use the chain as a settlement rail and translate its mechanics into familiar payment concepts without hiding risk or uncertainty.

  • CALL_EXCEPTIONethers v6
Backend 8 min

Requests hang waiting for a database connection

“Under load, latency jumps to the pool timeout, the database CPU is fine, and logs show connection-acquire timeouts or "too many clients".”

A pool is a fixed set of slots. Leaks, long transactions, and too many app instances each drain it; raising the limit usually moves the queue instead of removing it.

  • 53300PostgreSQL SQLSTATE
  • 25P03PostgreSQL SQLSTATE
  • 57014PostgreSQL SQLSTATE
Backend 8 min

A migration locks a table and requests pile up

“A deploy runs an ALTER TABLE or CREATE INDEX, and every query touching that table stalls until the migration finishes or is killed.”

Most ALTER TABLE forms need ACCESS EXCLUSIVE. While waiting behind one long query, the DDL also blocks every request queued after it, so a fast change can still cause an outage.

  • 55P03PostgreSQL SQLSTATE
  • 57014PostgreSQL SQLSTATE
Backend 7 min

Webhooks arrive twice, late, or out of order

“An order is fulfilled twice, a subscription flips back to an old status, or an update never lands because the webhook handler trusted delivery order.”

Webhook delivery is at-least-once with no ordering guarantee. Verify, record the event ID, acknowledge fast, and let a worker apply current provider state idempotently.

Backend 7 min

A third-party API starts returning 429

“Batch jobs or a traffic spike hit a provider limit; requests fail with 429, retries make it worse, and the provider may temporarily block the key.”

A rate limit is shared capacity. Throttle before sending, honor the server's retry hints, and back off with jitter so workers do not retry in lockstep.

  • 429HTTP status codes · RFC 6585
  • 503HTTP status codes · RFC 9110
Frontend 7 min

Hydration fails or the page flickers after SSR

“The console reports that server-rendered HTML did not match the client, or production logs show React error #418, and parts of the page re-render, flicker, or lose event handlers.”

The first client render must produce the same tree as the server. Find the input that differs between the two environments and make it deterministic or defer it until after hydration.

  • 418React minified errors
Frontend 7 min

The UI shows old data after a save

“The save succeeds, but the list, detail page, or another tab keeps showing the previous value until a hard refresh.”

Every cache layer between the database and the pixel can serve the old value. Identify which layer answered, then make the write invalidate or update exactly that layer.

Frontend 8 min

CORS fails only in production or on preflight

“Requests work locally and in curl, but the deployed app shows 'blocked by CORS policy', the OPTIONS request fails, and fetch rejects with a generic TypeError.”

CORS is enforced by the browser from response headers. Read the exact reason in the browser console and the raw preflight exchange, then fix the server or edge layer that produced the headers.

Mobile 9 min

The app works in debug but crashes in release

“Everything works from Metro or Xcode, but the release build, TestFlight, or Play internal track crashes on launch or on one screen, with a minified or hex-only stack trace.”

A release build is a different program: precompiled Hermes bytecode, R8-optimized native code, build-time environment, and no dev server. Symbolicate first, then diff what changed between the two builds.

  • SIGABRTApple crash reports
  • EXC_BAD_ACCESSApple crash reports
Mobile 10 min

Offline edits conflict or vanish on reconnect

“Users edit while offline; after reconnecting, their changes overwrite someone else's, get overwritten, or are applied twice.”

Queue intentions durably, replay them idempotently, and make every write state which version it was based on. Choose the merge policy per field instead of letting arrival order decide.

System design 9 min

A brief blip turns into a long outage

“A dependency hiccups for seconds, but traffic to it multiplies, error rates stay high after the root cause is gone, and it only recovers when load is shed manually.”

Retries at every layer multiply load exactly when the system has the least capacity. Retry in one place, within a budget and a deadline, and let overloaded services reject work cheaply.

  • 503HTTP status codes · RFC 9110
  • DEADLINE_EXCEEDEDgRPC status codes
System design 8 min

One bad message blocks or floods the queue

“Queue depth or consumer lag climbs, consumers look busy, and logs show the same message ID failing over and over.”

Bound delivery attempts, move messages that exhaust them to a dead-letter queue with the failure reason, and make consumers idempotent so redrive is safe.

System design 7 min

The database spikes when a hot cache key expires

“Load is flat for minutes, then a popular key expires and hundreds of requests miss at once, all run the same expensive query, and latency or DB CPU spikes on a regular rhythm.”

A cache hides load until a hot entry expires. Make sure only one caller recomputes a key, everyone else gets the old value or waits, and expiries don't line up.

  • 57014PostgreSQL SQLSTATE
Web3 8 min

A transaction is pending forever and blocks the rest

“One transaction never confirms, and every later transaction from the same account sits behind it.”

An account's transactions execute strictly in nonce order. Find the lowest unmined nonce, then replace that exact nonce with higher fees or a no-op.

  • REPLACEMENT_UNDERPRICEDethers v6
  • NONCE_EXPIREDethers v6
  • TRANSACTION_REPLACEDethers v6
Web3 10 min

A deposit was credited, then vanished after a reorg

“The indexer saw a deposit and credited the user, but the block was reorganized and the transfer no longer exists on the canonical chain.”

Separate seen, safe, and final. Credit spendable balance only at a block your risk model accepts, and make crediting idempotent per on-chain event.

Web3 8 min

Signatures fail because the wallet is on the wrong chain

“Users sign successfully, but the server rejects the signature or the transaction goes to a different network than the app expects.”

Chain ID is part of what gets signed. Make the server own the expected chain, make the client switch to it explicitly, and verify every signature against that chain.

  • 4902MetaMask wallet RPC errors
  • 4901EIP-1193 provider errors
  • 4001EIP-1193 provider errors
Web3 7 min

Balances and nonces flip between refreshes

“The same address shows a new balance, then the old one, then the new one again; nonces occasionally go backwards.”

Your RPC endpoint is usually a pool of nodes at slightly different heights. Each latest read can come from a different chain tip, so pin the block you read from and never let observed height move backwards.

  • NONCE_EXPIREDethers v6

HOW IT WORKS

Rebuild the mechanism, not just the fix.

23 of 23 explainers

System design 12 min

WebSockets, from Upgrade to close frame

What actually happens when a browser opens a WebSocket, and what keeps it alive?

A WebSocket is one HTTP request that asks to stop being HTTP. After a 101 (or an HTTP/2 extended CONNECT), both sides exchange small framed messages over the same connection until one sends a close frame or the network quietly drops it.

  • JavaScript
  • TypeScript
  • Go
  • Python
  • Rust
  • Elixir
  • Swift
Backend 11 min

The life of an HTTPS request

What actually happens between calling fetch() and getting a response?

Before your request leaves the machine, the client resolves a name, opens a transport, negotiates TLS and an HTTP version, and only then sends bytes, usually to a CDN edge rather than your origin. A warm, reused connection skips all of that, which is why connection reuse and timeouts matter more than most code-level tuning.

  • JavaScript
  • TypeScript
  • Go
  • Python
  • Rust
  • Java
  • Shell
Backend 12 min

OAuth authorization code flow with PKCE

What actually happens between clicking "Sign in" and calling an API with a token?

The browser carries a short-lived, single-use code; the client trades it for tokens over a back channel, proving with PKCE that it is the same client that started the flow.

  • TypeScript
  • Python
  • Go
  • Java
Backend 11 min

Database connection pooling

What actually happens when your code asks for a database connection?

A pool keeps a bounded set of expensive, authenticated database sessions open and lends them out per query or transaction, so callers queue for a connection instead of each opening their own.

  • TypeScript
  • Go
  • Python
  • Java
  • INI
  • Rust
System design 12 min

How message brokers actually deliver

What actually happens between publish and ack, and why does every queue end up delivering duplicates?

Brokers hand out leases, not messages: a delivery stays owned by the broker until the consumer acks, and anything unacked is delivered again. Practical systems are at-least-once, so exactly-once is something you build from dedupe plus idempotent side effects.

  • TypeScript
  • Java
  • Python
Web3 14 min

An Ethereum transaction from signing to finality

What actually happens between clicking Send in a wallet and an Ethereum transaction becoming final?

A transaction is a signed, typed message keyed by (sender, nonce). It waits in mempools until a block builder includes it, then gains confidence in stages: included, safe, and finalized about two epochs later.

  • TypeScript
  • TypeScript (React)
  • Shell
  • Python
  • Rust
Foundations 11 min

The JavaScript event loop: tasks, microtasks and rendering

Why does a promise callback run before setTimeout(fn, 0), and why does one slow handler freeze the whole page?

One thread runs one task to completion, then drains every queued microtask, then the browser may render a frame. Promises and await continuations are microtasks, timers and events are tasks, so microtasks always cut the line and nothing at all happens while your code is on the stack.

  • JavaScript
Foundations 12 min

Scope, closures, this and prototypes in JavaScript

Why is this undefined in my callback, why do all my loop handlers see the last value, and what does class actually create?

Variables resolve lexically, by where code is written; this resolves dynamically, by how a function is called. Closures keep their defining scope alive, and class is syntax over constructor functions and a prototype chain.

  • JavaScript
Foundations 13 min

The TypeScript type system and where it stops

What does TypeScript actually guarantee, and why can a fully typed app still crash on bad data?

TypeScript is a compile-time checker for JavaScript: it compares shapes structurally, narrows types through control flow, and then erases every type before the code runs. Anything that enters at runtime (JSON, env vars, forms, messages) is unchecked until you validate it.

  • TypeScript
  • JSONC
Foundations 14 min

Node.js runtime: V8, libuv and the event loop

What is Node.js actually made of, and what decides whether my code blocks every other request?

Node.js is V8 (the JavaScript engine) plus libuv (an event loop and a small thread pool) glued together by C++ bindings. Your JavaScript runs on one thread; I/O is handed to the kernel or the thread pool, and its callbacks come back through the event loop's phases.

  • JavaScript
  • Shell + TypeScript
Foundations 13 min

Express vs Fastify: middleware chain vs lifecycle hooks

How do Express and Fastify each turn a request into a response, and when should I pick one over the other?

Express runs one ordered list of (req, res, next) functions until something ends the response. Fastify routes first, then runs a fixed series of typed hooks around a handler, validating input and serializing output from JSON Schema.

  • TypeScript
  • JavaScript
Backend 15 min

One JSON HTTP server, eight runtimes

What does the same small JSON API look like across languages, and what actually differs underneath?

Every stack parses HTTP, routes, decodes JSON and writes a response in roughly the same dozen lines. The real difference is the concurrency model: what runs your handler, what a blocking call stalls, and how the process uses more than one core.

  • JavaScript
  • TypeScript
  • Python
  • Go
  • Rust
  • Java
  • C#
  • Elixir
Frontend 12 min

Workers everywhere: which "worker" do you mean?

Web Worker, Service Worker, worker_threads, job worker, Cloudflare Worker: what does each one actually run, and when do I need which?

"Worker" names at least eight different things that share one idea: run code somewhere other than the thread or process handling the user's request. They differ in where they run, how long they live, what they can touch, and how you talk to them.

  • JavaScript
  • TypeScript
Foundations 14 min

Multithreaded JavaScript: clone, transfer or share

If JavaScript is single-threaded, how do workers run in parallel, and what does it cost to move data between them?

Each JavaScript thread is its own agent with its own heap and event loop; parallelism comes from running several agents and passing data between them. You can copy data (structured clone), move ownership (transfer), or share raw memory (SharedArrayBuffer), and each step trades safety for speed.

  • JavaScript
  • HTTP
Frontend 13 min

Browser storage: what lives where, and for how long

Cookies, localStorage, IndexedDB, Cache API, OPFS: how much can I store, how long does it survive, and how do Chrome, Firefox and Safari differ?

Browsers give each origin one quota shared by IndexedDB, the Cache API, OPFS and service worker registrations, plus small separate stores for cookies and Web Storage. All of it is best-effort by default: the browser can delete an origin's data under pressure, and Safari also deletes script-written data after 7 days of use without interaction.

  • TypeScript
  • JavaScript
  • HTTP
Frontend 13 min

Web Components: custom elements, shadow DOM and where they fit

What does the browser actually give you with custom elements and shadow DOM, and when are they the right building block?

Web Components are three platform features used together: custom elements (your own tag with lifecycle callbacks), shadow DOM (a scoped subtree for markup and CSS) and templates. They give you framework-neutral UI primitives, at the cost of doing state, rendering and SSR yourself or with a thin library such as Lit.

  • JavaScript
  • TypeScript
  • HTML
  • TypeScript (TSX)
  • TypeScript + Vue SFC
Architecture 15 min

Micro-frontends: integration styles, costs and when not to

How do independently deployed frontends get stitched into one product, and what does that cost?

Micro-frontends split one user-facing product into parts that separate teams build and deploy on their own, then compose them at build time, on the server or edge, or in the browser at runtime. They solve an organizational bottleneck and charge you for it in payload, version skew and operational complexity.

  • TypeScript
  • HTML + JavaScript
  • TypeScript (TSX)
  • JavaScript
System design 14 min

Polling, SSE, WebSockets, push and webhooks: choosing a channel

When the server has something new, how should the client find out, and what does each option cost?

Every real-time mechanism trades latency against connections held, infrastructure friction and battery. Pick by direction (who talks), how fresh the data must be, whether the client is even running, and what your proxies and load balancers already handle well.

  • JavaScript
Architecture 14 min

Architecture patterns and when to use them

Layered, hexagonal, vertical slices, monolith, microservices, serverless: which pattern fits which problem, and what does each one actually cost?

Architecture patterns answer two separate questions: how code inside a deployable is organised (layered, hexagonal, vertical slices, MVC) and how deployables are cut (monolith, modular monolith, microservices, functions). Pick the code structure for change locality and testability; pick the deployment topology for team autonomy and operational needs, and pay for distribution only when evidence demands it.

  • TypeScript
  • Go
  • Java
  • JavaScript
Architecture 16 min

Event-driven architecture: events, sagas, outbox and read models

What does "event-driven" actually mean, and how do you publish events, coordinate multi-service workflows and keep read models correct without distributed transactions?

"Event-driven" covers four different patterns: event notification, event-carried state transfer, event sourcing and CQRS, each with different coupling and costs. Making any of them reliable comes down to a few mechanics: write the event in the same transaction as the state (outbox), relay it with CDC or polling, consume idempotently, coordinate long workflows with sagas, and design the UI for eventual consistency.

  • TypeScript + SQL
  • TypeScript
  • HTTP
Backend 15 min

Database types and how to choose one

Relational, document, key-value, wide-column, graph, search, OLAP, vector: which one does this access pattern actually need?

Each database family is a bet on one shape of data and one set of queries, and it pays for that with weakness elsewhere. Start with Postgres, then add a specialised store only when a measured access pattern outgrows it, and keep one system as the source of truth.

  • SQL
  • TypeScript
  • Redis commands
  • Cypher
System design 16 min

System design foundations

What are the building blocks of a typical web system, and how do you reason from requirements to a design that holds up?

System design is a loop: turn requirements into numbers, sketch the simplest architecture from standard parts (load balancer, stateless services, cache, database, queue), find the component that breaks first, and fix only that.

  • TypeScript
  • nginx
System design 18 min

Replication, sharding and consistency

When data lives on more than one machine, who accepts writes, where does each key go, and what can a reader actually observe?

Replication copies the same data to several nodes for availability and read scale; sharding splits data so each node owns a part for write scale and size. Every choice about how copies stay in sync is a choice about which stale or reordered reads your users can see.

  • TypeScript
  • SQL

INTERVIEW PRACTICE

Answer first. Then check.

All 103 questions

NOT ANOTHER DOCS SITE

Designed to rebuild judgment,
not collect bookmarks.

Symptom first

Find the guide using the half-remembered production problem—not the term you forgot.

Then and now

Reconnect older experience with the tools and practices teams use today.

Explain it back

Each guide ends with a recall prompt. If you cannot explain it, you do not own it yet.

“Vibe coding made us faster.
Fish Memory keeps us dangerous.”

Built for experienced engineers who use AI every day—and still want their instincts available when the model is wrong.

fishmemory

Open field notes for fallible humans.

Guide reviews: 2026-09-23 – 2026-10-07. Error codes dated separately.