Ask

shut the api off 3 weeks ago and stripe still billed 41 accounts last night

Archiving a price stops new subscriptions being created against it. It does nothing to the ones that already exist - they hold a reference to that price and keep renewing until something explicitly cancels them.

Order I would do it in, today:

  • page through stripe subscriptions list --status active --limit 100 and collect the ids
  • subscription.cancel(id) on each, not cancel_at_period_end, since there is no product left to deliver
  • refund the last invoice on each one, in full
  • then email, after the refunds are in flight, so the email says "already refunded" instead of "will refund"

The six disputes are the expensive part. You pay the dispute fee whether you win or lose, and a sudden cluster of them on a dormant account is how an account ends up under review. Refunding a charge that is already disputed does not withdraw the dispute either - you still have to respond to it.

186 · in/sunset-or-sell ·

export zip dies at 512mb and takes the whole worker down, 12 days to shutdown

Do not zip. The zip is a requirement you invented.

Generate a manifest per account: manifest.csv with path, size, sha256 and a presigned URL valid for 30 days, plus a six line script at the top of the page that loops over it with curl. For the handful of big accounts, issue a scoped read-only token and tell them to point rclone at their own prefix - a 14 GB customer has someone technical.

You get to keep the whole thing stateless, you never hold a byte in memory, and resumability is free because each object is its own request.

165 · in/sunset-or-sell ·

msw or a real neon branch per PR when the suite has 9 minutes of budget

Test the policy from outside, as the app role. Set the role and the request claims exactly the way your platform does at runtime, then assert that selecting another tenant's rows returns zero rows.

Assert on the row count, not on an error message. Error text changes between versions and you will spend a morning on it for no benefit.

51 · in/built-to-last ·

23 domains and the renewals are getting silly - where do people park the ones they are not using?

For parked domains I use an at-cost registrar, meaning one that charges the registry fee plus the ICANN fee with no markup and no separate renewal price. That is the whole point for domains that will never generate anything: the sticker price and the renewal price are the same number, forever, and it goes up only when the registry raises it.

Two caveats. First, the at-cost model usually means you use their nameservers, which is fine for parked names and a consideration for client work. Second, the registry has been raising .com wholesale on a schedule for several years now, so nobody's renewal is truly flat, it is just not marked up on top.

184 · in/hosting-and-domains ·

$340 mrr and 4.5 hours a month - keep it on life support or turn it off?

Sell it. $340 MRR with low churn and five years of history lists somewhere around 2.5-3.5x annual profit, so call it $6.5-9k before fees. There are people who run six of these at once and for whom your 4.5 hours is thirty minutes because they already have the runbooks.

You will not retire on it. You will also never think about the CSV import again.

69 · in/sunset-or-sell ·

Which cloud free tiers are forever and which are a twelve month trial wearing a costume?

Oracle's Always Free is the most generous of the perpetual ones and it genuinely doesn't expire: their docs say the always-free resources stay free for the life of the account, whether or not the trial credits ran out.

What you get: up to two of the tiny AMD micro instances (an eighth of an OCPU and 1GB memory each), plus Arm-based Ampere capacity totalling 2 OCPUs and 12GB memory, plus 200GB of block storage in your home region. The Arm allocation is the useful one: you can put it all in a single instance.

The catch is written down and people still get caught by it: idle instances can be reclaimed if CPU, network and memory all sit under 20% for seven days. A genuinely quiet side project can be considered idle.

268 · in/free-tier-limits ·

2,300 bullmq jobs stuck in active after a deploy, lockduration is default

Both, but mostly the deploy. Two separate problems that look like one.

The lock. Your job runs three times longer than lockDuration. The lock is renewed while the job is alive and reporting; a job that goes completely silent for 90 seconds looks dead to the stalled checker, which hands it to another worker. Either raise lockDuration comfortably above your p99 job time, or call job.updateProgress() every few seconds inside the work so the lock keeps being renewed. The second is better because it also gives you progress for free.

The deploy. Your old pods were killed with jobs in hand. Handle SIGTERM: stop accepting new jobs, await worker.close(), and set the container's termination grace period longer than your longest job. The default grace period is 30 seconds and your jobs are 90, so every deploy guarantees a pile of orphans.

Together those two explain the exact shape you saw - active climbing, completed flat, ids repeating.

176 · in/queues-and-jobs ·

Site on one host, email on another, domain at a third - where should the DNS actually live?

One thing to know before you consolidate everything at an at-cost registrar, because it is the sort of detail that only bites later: domains registered through Cloudflare Registrar have to use Cloudflare nameservers, and their own documentation says you cannot switch to another DNS provider's nameservers while the domain is registered there. That is completely fine if you were going to use their DNS anyway, and it is a real problem for a client whose IT department runs their own DNS and wants the zone on their infrastructure. Decide that before the transfer, not after.

172 · in/hosting-and-domains ·

buyer pulled out after diligence found 62% of mrr in one account

Diligence connects to Stripe and reads it directly. Three subscriptions on one company domain paid by the same card is more suspicious than one honest big customer, and "I restructured the billing so it would look better" is the kind of discovery that ends a deal and follows you around. Fix the risk. Do not repaint it.

21 · in/sunset-or-sell ·

Inherited six AWS Data Pipeline jobs from someone who left in 2022, move to Glue, Step Functions or off entirely

First thing to know is that the decision is partly made for you: AWS Data Pipeline is closed to new customers and the service is in maintenance mode with no new features or region expansion planned, and AWS publishes its own migration guidance pointing at other services. Existing pipelines keep running, so there is no fire, but you are maintaining something with no road ahead of it and no new hires who will have seen it. Your five copy jobs are the easy part and should not be treated as a migration project at all, they are a scheduled COPY statement. The EMR job is the one that deserves actual thought.

118 · in/data-pipelines ·

Everyone says just practise, practise what, exactly? What did you actually drill?

Worth separating the two possible problems before you spend six months. If you know what to say and cannot say it because your heart is going, that is not a skill deficit and no amount of drilling fixes it - that is worth raising with a professional, and it was for me. If you are calm and simply do not know the moves, drills are exactly right. I spent two years practising skills I already had while ignoring the actual problem.

218 · in/conversation ·

new to playwright: how do people actually reset the db between specs

You are not missing anything. The tutorials are describing a serial suite and nobody updated them.

The pattern that survives parallelism is: do not reset, isolate. Every test creates its own tenant/org/user with a unique id and only ever touches rows under it. Truncate once at the start of the run and never again.

Two things fall out of this for free:

  • your app gets a genuine multi-tenancy test on every run, because a test that can see another test's data has found a real bug in your scoping
  • adding workers costs nothing, because there is no shared mutable state to fight over

The version that scales further is a worker-scoped fixture: one seeded org per worker, created once, reused by every spec in that worker.

178 · in/built-to-last ·

pg-boss or redis for 20 jobs a minute on one $12 box

Use a maintained library rather than hand-rolling the table. The naive version is about forty lines and the missing four hundred are scheduling, retry with backoff, visibility timeouts, archiving completed rows, and the migrations to change any of that later without downtime.

Every hand-rolled queue I have inherited was correct for the first six months and then grew a WHERE status = 'stuck_weird' clause.

84 · in/queues-and-jobs ·