Ask

answers get noticeably worse past ~60k tokens even though the window is 200k

Because a long window is a capacity, not a promise about attention. Everything in there competes, and by 60k a large fraction of your context is stale: old file versions, superseded plans, tool output nobody needs any more. The model has no way to know that the version of parseInvoice from turn 6 is dead. Both versions are equally present and equally plausible.

What works:

  • one task, one session. When the task changes, start over. This is the biggest single one
  • keep the durable stuff in files, not in the conversation. A PLAN.md you edit as you go survives a restart; a plan described in turn 4 doesn't
  • after a significant change, tell it to re-read the file instead of relying on what it saw earlier. Cheap, and it kills the stale-signature class of error outright
  • when you feel the wobble, don't fight it. Ask for a handoff summary: what's done, what's left, which files matter - and paste that into a fresh session

Restarting feels like losing progress. It costs ninety seconds and it's usually the fastest thing available to you.

187 · in/ai-pair-coding ·

node container exits 137 under load on a 2gb vps with mem_limit 512m

Node doesn't know about your cgroup limit. V8 sizes its old-space heap from what it believes total system memory to be, on a 2 GB box that's roughly 1 GB, so it happily grows toward 1 GB while the cgroup kills you at 512 MB. It isn't failing to GC, it thinks it has plenty of room left.

Tell it the truth:

environment:
  NODE_OPTIONS: --max-old-space-size=384
mem_limit: 512m

Leave headroom, because old space isn't the whole RSS - buffers, the code cache, native modules and stacks all live outside it. 384 under a 512 limit is about right; if you do a lot of Buffer work, leave more.

Then watch it. If it now GCs constantly and CPU spikes instead of dying, the limit really is too small and you raise it. Nine times out of ten this is the entire bug.

176 · in/docker-deploys ·

Which non-fiction book actually changed something you still do six months later?

I logged this because I got suspicious of my own answers. Forty three non-fiction books over three years, and by my own honest audit three of them left a behaviour I still do: one gave me the two minute rule for filing, one gave me a way to run a meeting that I have used weekly since, and one changed how I cook rather than how I work. That is a hit rate of about seven percent, which I think is normal and worth knowing before you buy the next stack.

78 · in/book-recs ·

Town sewer is coming down our road and the hookup quote is 18k - do we keep the septic?

Mild disagreement with the resale argument people will make. In our market, buyers looking at rural properties expected septic and did not pay a premium for sewer, the appraiser did not adjust for it either. If you are somewhere that people commute from and lots are being subdivided, sure. Where we are it moved nothing, so decide on running cost and risk, not on an imagined future buyer.

92 · in/well-and-septic ·

agent rewrote 340 lines to fix a two-line bug, third time this week

Constrain the blast radius mechanically instead of asking nicely.

What works for me, in order of effect:

  • give it a failing test and say the only success condition is that test passing with no other test changing. Now there's a definition of done that isn't "improve the code"
  • state the line budget out loud. "Fix this with the smallest possible diff. If the fix is more than 10 lines, stop and explain why before writing anything." The explain-first clause is the important half: it turns an unwanted refactor into a sentence you can say no to
  • keep a rule in the repo config: no unrequested refactors, no renames, no new abstractions unless asked

The stop-and-explain pattern changed my day-to-day more than anything else. Most of the time it comes back with "it's three lines" and just does it.

201 · in/ai-pair-coding ·

Kimchi I made in March still smells fine in July - when does old kimchi stop being good and start being a problem?

Sour kimchi is not old kimchi, it is a different ingredient, and Korean home cooking treats it that way. Mine routinely goes a year in the fridge, and by then it is only for stew, fried rice and pancakes, where the softness stops mattering. What you have described, submerged, sour, fizzy, soft, no film - is exactly what a year-old jar looks like at month four. Keep it.

189 · in/fermentation ·

read every ai diff line by line, or lean on tests, at 15 merges a week

Neither uniformly. Route by blast radius, because that's the thing that actually varies.

What we landed on after about eight months:

  • anything touching auth, payments, permissions, migrations or deletion: read every line, run it locally, second reviewer. No exceptions regardless of how small the diff looks. Maybe 15% of PRs
  • anything where a wrong result is caught by a test that already exists: skim the diff shape, read the test changes carefully, merge. But if a test was modified rather than added, that's a stop sign: it's the most common way model-written code goes green
  • everything else: read it properly, don't agonise

The highest-value rule in there is treating a modified assertion as a blocker. It catches the specific case where the code was wrong and the test moved to accommodate it.

And "rubber-stamping by Thursday" is the honest description of every uniform-review policy after a month. Design for it rather than pretending.

152 · in/ai-pair-coding ·

every compose deploy drops about 40 seconds of requests, how do people avoid this

Minimum viable is healthcheck plus a second replica plus letting caddy route around the unhealthy one.

api:
  deploy:
    replicas: 2
  healthcheck:
    test: ["CMD", "wget", "-qO-", "http://localhost:3000/healthz"]
    interval: 5s
    timeout: 2s
    retries: 3
    start_period: 20s

Then docker compose up -d --wait, and caddy load-balancing over both with a health check on /healthz. It pulls an unhealthy backend out of rotation instead of 502ing at it.

That gets you most of the way, but compose will still cycle both replicas at once unless you push them one at a time. For true rolling on plain compose the honest answer is you script it: start new, wait for healthy, drain old, stop old. It's about 30 lines of bash and it works fine.

The other honest answer is that this is exactly what Kamal does, and Kamal is not kubernetes. Single VPS, compose-shaped config, does the health-check-and-swap for you.

168 · in/docker-deploys ·

Offer accepted on a place with well and septic after a lifetime on city water - what do I insist on before closing?

Honest list of the trade-offs since you asked for pros and cons. No monthly water or sewer bill and often better tasting water; against that, you own every repair, a power cut means no water, and you are responsible for testing that a utility would otherwise do for you. Set aside a maintenance fund from day one and treat it as the bill you are not paying. Over ten years mine has still come out cheaper than the town supply my sister pays for.

164 · in/well-water ·

every generated test mocks the thing it is supposed to test, 40 files in

380 tests was the wrong ask. Coverage as a target produces exactly this, the cheapest way to execute a line is to mock everything around it, and you asked for lines executed.

Two changes fix it.

Ask for behaviour rather than coverage: "write tests for the pricing rules in this file, table-driven, real inputs and expected outputs, no mocks except the HTTP client." Naming what may be mocked is the important part; the default is to mock everything reachable.

Then verify with mutation testing rather than coverage. Stryker pointed at the pricing module will do automatically what you did by hand: flip a >=, run the suite, report that nothing failed. Start with one module, it's slow. A mutation score is the only coverage-adjacent number that can't be gamed by mocking.

Also: delete the 40 files. Seriously. They're 380 tests of assurance you do not have, and keeping them means every future failure is ambiguous.

164 · in/ai-pair-coding ·