I used to pay ~$700/year in subscriptions to collect testimonials and transcribe recordings.
Now I run my own apps on a $5/mo VPS, plus API usage costs.
I also self-host Katabench on a VPS fleet: a few thousand users, p99 latency under 70ms.
This is why I like self-hosting: low costs, good performance, and software I can change to fit how I work.
I put those foundations into Pragmatic Self-Hosting. I'll walk you through the single-VPS setup below so you can use it for your own apps.
Check out Pragmatic Self-Hosting:
https://t.co/NHomMGU39H
We've given all Pro, Max, Ultra, and Team users one free full reset, across all models and limits. Use it anytime before December 10 at 2:00PM PT.
We recently fixed a few small issues that used more limits than intended, and the Fable resets didn't do much for those of you who'd already hit your weekly limits for all models. While these issues didn't affect everyone, we want to make up for the trouble.
You'll find it in Settings > Usage, or at https://t.co/5YRzheAZyQ.
@LuckyGoodrich Usually a rough outline with AI based on my idea, and then refine it with my own thoughts. Very important that I not forget how to write (and thus think), so I try to exercise that muscle daily
The first issue of my newsletter went out to a few hundred people, and I almost didn't make it past issue 10.
I wrote a draft, second-guessed it, rewrote it, and hit send with my stomach in a knot.
That was more than 210 issues ago. What got me through was a decision I made up front: one issue, every week, no exceptions.
I wrote about those four years here: https://t.co/6LMDp3SuZq
Whether a human or an agent wrote the code, I ask the same questions.
Does this rule belong in the domain model?
Will this change break an existing API client?
What happens when this call fails?
The agent makes coding faster. But it doesn't change what makes it correct.
You can extract a service from a monolith later. You can't easily un-distribute a system.
I split when something concrete forces it: a team blocked on every deploy, or a module with its own scaling needs.
"The monolith feels messy" isn't one of those reasons.
Union types are coming in C# 15.
I've wanted this one for years.
I've written a lot about the Result pattern. Take a method as small as GetUser(42). Its return type says User. You have to open the method to find out it throws if user 42 doesn't exist. That's a lot to hide in a lookup.
With a union, I can give GetUser a return type called UserResult with two cases. I can return a User or a NotFound. At the endpoint, I switch on the result. A User gets a 200. NotFound(42) gets a 404, and I still have the ID that was missing.
The part I'm most excited about comes later. Say we add a third case. The compiler can point me to the switch expressions that still handle only two. I get to fix those while the change is fresh in my head.
Here's how to get started with union types: https://t.co/a5dfwfONX7
I don't want a slow file upload to tie up my API.
Look at B. The API receives the file, then sends it to storage. Streaming can keep memory use low. But the file still uses the API's network connection and bandwidth for the whole upload.
For large files, I choose A.
The API checks who you are and what you can upload. It saves a pending file record, then returns a short-lived signed URL. Your browser sends the file straight to storage.
That URL needs tight scope. It should allow the intended upload to the right object key. Before I mark the file ready, I also check what reached storage against the pending record.
Small files may be fine through the API. A proxy also gives you a place to inspect bytes as they pass through.
The Upload Directly to Storage puzzle on Katabench lets you draw the auth path and the file path:
https://t.co/jwEb477tMZ