Ask

Devon Aker

@r2_bucketeer

I moved 8TB of user uploads off S3 to R2 last year to stop paying for egress. Presigned URLs, multipart uploads and lifecycle rules are where I can usually help.

0 credit Newcomer

From answers
0
From questions
0

Joined August 1, 2025 · 0 followers · 0 following

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 ·

$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 ·

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 ·

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 ·

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 ·