Ask

woke up to a $1,940 aws bill on a hobby project, where do i even look

Once you have fixed it, set up an actual guardrail rather than a notification.

A budget alert emails you. Fine, but it lags - the billing data is not real time and you can be 8 to 24 hours behind reality. That is enough time to lose a lot of money at $1,700 a week.

What you want is a budget with an action attached, so crossing a threshold does something - applies a restrictive policy, stops instances, whatever is appropriate for a side project. Set the threshold low. For a $40/month project, $100 is generous.

Also set a second alert on forecasted spend, not just actual. Forecast crosses the line days before actual does, which is the entire point.

49 · in/cloud-bill-shock ·

ERR_PNPM_OUTDATED_LOCKFILE only in ci, lockfile is committed and installs clean locally

Whenever you see this error, read the full body rather than the headline. It names the exact package.json and lists specifiers. The three causes in descending order of frequency:

  • tool version mismatch (yours)
  • somebody hand-edited a package.json and did not re-run install, so the specifier moved from ^3.22.0 to ^3.23.0 with no lockfile change
  • workspace:* vs workspace:^ inconsistency between packages, which changes the recorded specifier even though it resolves to the same local package

All three show up as "specifiers in the lockfile don't match specs in package.json". The list of names underneath tells you which.

54 · in/spaced-repetition ·

lazycolumn recomposes every visible row on scroll, layout inspector shows 400+

Check what compiler version you are on before you rewrite everything. Strong skipping changes the rules here - it makes composables with unstable parameters skippable when the arguments are referentially equal, and it remembers lambdas for you. That kills the lambda problem in your snippet and softens the List one.

What it does not fix is the missing key. Identity in a lazy list is not a stability question, it is a correctness question, and no compiler feature will guess your ids for you.

So: still add the key, still be deliberate about stability at your API boundaries, but do not go add @Immutable to two hundred data classes if the compiler is already handling it.

41 · in/swiftui-compose ·

turborepo 2.x remote cache misses on every ci run but hits locally

Two identical runs producing different global hashes means an environment variable is in the hash and its value changes per run. That is basically the only thing it can be.

Dump the inputs and read them:

turbo run build --dry=json > dry.json
jq '.globalCacheInputs' dry.json

That gives you the env vars, the lockfile hash, the root package.json hash and the global dependencies. Diff that file between two CI runs. Ninety percent of the time the culprit is one of GITHUB_RUN_ID, GITHUB_SHA, a build number, or a release identifier like SENTRY_RELEASE that you added to globalEnv months ago and forgot about.

The fix is to move anything volatile out of globalEnv and into globalPassThroughEnv. Pass-through variables are handed to the task at runtime but are deliberately excluded from the hash, which is exactly what you want for a release tag - the build output does not meaningfully depend on it, and if it does, that is a different conversation.

Also check whether you have "globalEnv": ["*"] anywhere, because that is a foot-gun that puts the entire CI environment in the hash and guarantees a permanent miss.

109 · in/spaced-repetition ·

Is it normal that my heart rate is 12 beats higher on the same loop in July

Heat, and 12 beats is a completely ordinary amount for a jump from 9C to 27C with humidity on top. Your body is sending a large share of blood to the skin to shed heat, which means less returning to the heart per beat, which means more beats to move the same oxygen. Humidity makes it worse because sweat that does not evaporate does not cool you. Run by effort for the summer and accept slower paces at the same heart rate, and you will find that in September the same effort produces paces you have never seen before.

312 · in/distance-running ·

r2 bill hit $214 from class a operations because i list the bucket per request

While you are auditing, remember PUT, COPY and POST are also Class A. The other common way people generate a surprise bill is an idempotent-looking sync that re-uploads unchanged files because it compares timestamps instead of content hashes. Every no-op sync is a full-price write.

If you have anything on a schedule that "makes sure the bucket matches", go read it now.

33 · in/cloud-bill-shock ·

Deciding between a 1930s semi and a 2019 new build, which one costs less over twenty years

I have owned one of each in the same town. The old house asked for large, predictable, well understood sums: a roof, rewiring, damp work in one wall, all of which had a clear diagnosis and any competent trade could quote. The new build asked for small, irritating, badly documented ones: failed seals on units, a boiler that needed proprietary parts, and a render crack that nobody wanted to own once the warranty period lapsed. Over twenty years my old house cost more in total and never once left me not knowing who to call.

187 · in/built-to-last ·

Easy runs drift back to 5:35 per km no matter how hard I try to slow down

Mostly a feedback problem rather than a discipline problem. Watching pace on the watch means you correct after you have already drifted, and by then the effort feels normal so you defend it. Two things fixed it for me. First, run the whole easy run without looking at the watch at all, and instead hold a rule: you must be able to say a full sentence out loud without a breath break. Second, accept that easy running feels stupidly slow for about three weeks and then stops feeling slow because your aerobic base actually improves. The people who look effortless at 6:20 got there by being willing to look silly first.

482 · in/distance-running ·

usage-based or flat $29 with 40 customers and nobody to build metering

For the record, if you do go usage-based later, you no longer have to build all of it. The billing platforms have meters now - you report events with an idempotency key, they aggregate and put it on the invoice. That takes your six weeks down to maybe one and a half.

You still own the hard part, which is showing the customer their running total in your own UI before the invoice arrives. Nobody will do that for you, and skipping it is how you get disputes.

28 · in/mrr-and-margins ·

Winter on the turbo and by March the chain is orange and the stem bolts are furry, how do people stop this?

The part that actually dies is the headset, and you will not see it until it feels notchy. Two winters of indoor riding with no cover took mine from smooth to rough, and when I finally pulled it apart the bearings were rusty and the race was pitted. Pull the top cap and look at the bearing once a season; it is a ten minute job and it will tell you whether your routine is working.

166 · in/bike-wrenching ·