<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Krabber on t0ul</title><link>https://t0ul.com/tags/krabber/</link><description>Recent content in Krabber on t0ul</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Fri, 09 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://t0ul.com/tags/krabber/index.xml" rel="self" type="application/rss+xml"/><item><title>Immutable deploys on a single box, with no downtime</title><link>https://t0ul.com/blog/immutable-deploys-one-box/</link><pubDate>Fri, 09 Oct 2026 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/immutable-deploys-one-box/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; runs on a single Beanstalk instance, which sounds like it should mean &amp;ldquo;deploys have a downtime window while the box restarts.&amp;rdquo; It doesn&amp;rsquo;t. Deploys are zero-downtime and they roll themselves back if the new version is sick. In this post I&amp;rsquo;ll walk through how one box manages that, because the trick is to never actually deploy onto the box that&amp;rsquo;s serving.&lt;/p&gt;</description></item><item><title>Email on a budget: sending, receiving, and a tiny forwarder Lambda</title><link>https://t0ul.com/blog/email-on-a-budget-ses/</link><pubDate>Wed, 07 Oct 2026 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/email-on-a-budget-ses/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;A social site needs email. It has to send activation links and password resets, and it needs an address people can actually write to. The expensive, heavy way is a mail provider and a hosted inbox. The &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; way is Amazon SES for sending, SES again for receiving, and a tiny Go Lambda to forward the few real messages to my own inbox. The whole arrangement costs cents a month, and I&amp;rsquo;ll walk through all three parts.&lt;/p&gt;</description></item><item><title>TLS all the way to the crab</title><link>https://t0ul.com/blog/tls-all-the-way-to-the-crab/</link><pubDate>Mon, 05 Oct 2026 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/tls-all-the-way-to-the-crab/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;Krabber runs on a single Elastic Beanstalk instance, with no Application Load Balancer in front of it. That&amp;rsquo;s a deliberate cost choice, since an ALB would roughly double the fixed monthly bill for a site that fits on one box. But it does take away the easy button for HTTPS, and this post is about getting that button back by hand.&lt;/p&gt;</description></item><item><title>Reading the scrapersphere</title><link>https://t0ul.com/blog/reading-the-scrapersphere/</link><pubDate>Sat, 03 Oct 2026 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/reading-the-scrapersphere/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;This one is a sequel to &lt;a href="https://t0ul.com/blog/the-day-krabber-net-went-dark/"&gt;the outage post&lt;/a&gt;. While I was busy chasing that, I noticed something else in the WAF dashboard: a spike. About 3,100 requests in a window where I normally get dozens. Roughly 2,100 allowed, 992 blocked, almost all from a single country, and almost all caught by the rate-limit rule.&lt;/p&gt;</description></item><item><title>The day krabber.net went dark</title><link>https://t0ul.com/blog/the-day-krabber-net-went-dark/</link><pubDate>Thu, 01 Oct 2026 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/the-day-krabber-net-went-dark/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;So &lt;a href="https://krabber.net"&gt;krabber.net&lt;/a&gt; went down. Not slow, not throwing an error page, just gone. My own browser couldn&amp;rsquo;t even find it.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve run krabber.net on and off for years, and this was from the latest time I spun it back up. A fresh spin-up came with a fresh kind of failure, one I&amp;rsquo;d never hit on the earlier rounds, which is exactly why it took me a while to place it.&lt;/p&gt;</description></item><item><title>Krabber: a Twitter clone in Go for under $100 a month</title><link>https://t0ul.com/projects/krabber/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://t0ul.com/projects/krabber/</guid><description>A Twitter clone in Go, live at krabber.net: one server, one DynamoDB table, and a cost model that keeps the bill under $100 a month at 10,000 daily active krabs.</description></item><item><title>Durable fan-out: background work that survives a crash</title><link>https://t0ul.com/blog/durable-fan-out/</link><pubDate>Thu, 28 May 2026 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/durable-fan-out/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;On &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt;, your home feed is called the Trench, and it&amp;rsquo;s built by fan-out. When you post a molt, that molt gets written once into the feed of every krab who follows you. For someone with a few hundred followers that&amp;rsquo;s a few hundred writes kicked off by one click, and it all happens in the background so the post feels instant.&lt;/p&gt;</description></item><item><title>Watching an $11 site: budgets, alarms, and a canary</title><link>https://t0ul.com/blog/watching-an-11-dollar-site/</link><pubDate>Thu, 19 Feb 2026 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/watching-an-11-dollar-site/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;A site I run alone needs to tell me when something&amp;rsquo;s wrong, because I&amp;rsquo;m not sitting there watching it. &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; has a small observability setup that covers three questions: is it up, is it misbehaving, and is it about to cost more than it should? All of it notifies one email address, and the whole thing is designed to stay inside the free allowances. Here&amp;rsquo;s how it&amp;rsquo;s put together.&lt;/p&gt;</description></item><item><title>A CI pipeline with a budget it can't exceed</title><link>https://t0ul.com/blog/a-ci-pipeline-with-a-budget-it-cant-exceed/</link><pubDate>Thu, 13 Nov 2025 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/a-ci-pipeline-with-a-budget-it-cant-exceed/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;I pay for &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; myself, so one of my rules is that the bill has to have a known ceiling, even on a bad day. I wrote a whole post on &lt;a href="https://t0ul.com/blog/metering-every-request-dynamodb-cost/"&gt;metering the database&lt;/a&gt; toward that goal. But there&amp;rsquo;s a scarier way to blow a budget than a greedy query: your own automation doing something expensive. A typo in Terraform, or a compromised GitHub Action, that spins up a big instance or flips you to a premium plan. So I gave Krabber&amp;rsquo;s deploy pipeline a budget it physically can&amp;rsquo;t exceed, enforced in IAM.&lt;/p&gt;</description></item><item><title>Keyless deploys: GitHub Actions into AWS with no stored secrets</title><link>https://t0ul.com/blog/keyless-deploys-github-oidc/</link><pubDate>Thu, 28 Aug 2025 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/keyless-deploys-github-oidc/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;For years the default way to let CI touch AWS was to mint an IAM access key, paste it into your CI secrets, and hope it never leaks. That key is long-lived, it&amp;rsquo;s a static secret sitting in a second system, and if it gets out, someone has your account until you notice and rotate it. &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; has none of those. Its GitHub Actions authenticate to AWS with zero stored credentials, using OIDC, and I want to show how that&amp;rsquo;s set up because it&amp;rsquo;s one of those security wins that&amp;rsquo;s also just less hassle.&lt;/p&gt;</description></item><item><title>Terraform in two stacks: the one you apply by hand, and the one CI applies</title><link>https://t0ul.com/blog/terraform-bootstrap-vs-prod/</link><pubDate>Thu, 22 May 2025 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/terraform-bootstrap-vs-prod/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;All of &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt;&amp;rsquo;s AWS infrastructure is Terraform, but it&amp;rsquo;s in two separate stacks, and that split is on purpose. One stack I apply by hand, exactly once. The other is applied automatically by CI on every merge. In this post I&amp;rsquo;ll explain why it&amp;rsquo;s two instead of one, because the reason is a nice little chicken-and-egg problem.&lt;/p&gt;</description></item><item><title>Moderation from a terminal: why you can't become an admin on the website</title><link>https://t0ul.com/blog/krabmin-moderation-krabctl/</link><pubDate>Thu, 13 Feb 2025 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/krabmin-moderation-krabctl/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;Any site where people can post needs moderation. &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; has a console for it called Krabmin: a report queue, bans, warnings, removing and restoring molts, and a log of every action. But the part I want to focus on is a deliberate restriction: there is no way to become an admin through the website. The highest role can only be granted from a terminal. Let me explain the setup and why that line matters.&lt;/p&gt;</description></item><item><title>Browser hardening: a strict CSP and the work to earn it</title><link>https://t0ul.com/blog/browser-hardening-csp/</link><pubDate>Thu, 07 Nov 2024 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/browser-hardening-csp/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;A Content-Security-Policy is the browser&amp;rsquo;s instruction sheet for what your page is allowed to load and run. A strict one is one of the best defenses you have against cross-site scripting, because even if some user content slips through unescaped, the browser refuses to run it. &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; sends a tight CSP on every response. But a strict policy isn&amp;rsquo;t a header you just paste in, it&amp;rsquo;s a header you have to make your app deserve, and that second part is the interesting bit.&lt;/p&gt;</description></item><item><title>Layered CSRF in Go: the new way and the old way, together</title><link>https://t0ul.com/blog/layered-csrf-in-go/</link><pubDate>Thu, 01 Aug 2024 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/layered-csrf-in-go/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;Cross-site request forgery is the attack where another site tricks your logged-in browser into making a state-changing request to Krabber, like posting or deleting, without you meaning to. It&amp;rsquo;s an old problem with well-known defenses, and Go recently grew a built-in one. &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; uses that new defense and three older ones at the same time, and I want to explain why I didn&amp;rsquo;t just pick the newest and call it done.&lt;/p&gt;</description></item><item><title>htmx instead of a single-page app</title><link>https://t0ul.com/blog/htmx-no-spa/</link><pubDate>Thu, 25 Apr 2024 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/htmx-no-spa/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; feels like a modern social app. You like a molt and the button updates, you follow a krab and it flips to Following, you scroll and more loads, and new molts announce themselves at the top. And there&amp;rsquo;s no React, no client-side router, and no front-end build step anywhere. It&amp;rsquo;s server-rendered Go with &lt;a href="https://htmx.org"&gt;htmx&lt;/a&gt; doing the interactive parts, and I want to show how little it takes, because people assume this kind of interactivity requires a framework.&lt;/p&gt;</description></item><item><title>A unique crab for every account, generated from seven digits</title><link>https://t0ul.com/blog/generated-crab-avatars/</link><pubDate>Thu, 18 Jan 2024 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/generated-crab-avatars/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;Every account on &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; gets its own little crab as an avatar, and no two are quite the same. There&amp;rsquo;s no uploading, no image processing, and no bucket full of avatar PNGs anywhere. Each crab is drawn as SVG from a short code, on the fly, and then cached at the edge. It&amp;rsquo;s one of my favorite small pieces of the project, so let me pull it apart.&lt;/p&gt;</description></item><item><title>Metering every request so the bill can't surprise me</title><link>https://t0ul.com/blog/metering-every-request-dynamodb-cost/</link><pubDate>Thu, 26 Oct 2023 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/metering-every-request-dynamodb-cost/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;I pay for Krabber out of my own pocket. That one fact drives every design decision I make, and it turns cost from a thing you check on the invoice at the end of the month into a thing you test in CI, the same way you test anything else.&lt;/p&gt;</description></item><item><title>Rate limiting in one table, no Redis</title><link>https://t0ul.com/blog/rate-limiting-in-one-table/</link><pubDate>Thu, 20 Jul 2023 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/rate-limiting-in-one-table/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;Rate limiting is one of those features you don&amp;rsquo;t think about until a bot is hammering your login page. &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; does it in three layers, and the middle layer, the app&amp;rsquo;s own limits, lives in the same DynamoDB table as everything else, with no Redis in sight. In this post I&amp;rsquo;ll walk through all three, because they each stop a different kind of abuse.&lt;/p&gt;</description></item><item><title>Sessions in DynamoDB, no Redis</title><link>https://t0ul.com/blog/sessions-in-dynamodb-no-redis/</link><pubDate>Thu, 13 Apr 2023 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/sessions-in-dynamodb-no-redis/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;The usual advice for web sessions is &amp;ldquo;put them in Redis.&amp;rdquo; And Redis is great. But it&amp;rsquo;s also one more thing to run, secure, back up, and pay for, and for &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; I didn&amp;rsquo;t want another box in the diagram. So sessions live in the same single DynamoDB table as the molts and the krabs. In this post I&amp;rsquo;ll walk through how, and the handful of rules that keep it correct, because a session store is one of those things that&amp;rsquo;s easy to get subtly wrong.&lt;/p&gt;</description></item><item><title>One table to rule the reef</title><link>https://t0ul.com/blog/one-table-to-rule-the-reef/</link><pubDate>Thu, 26 Jan 2023 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/one-table-to-rule-the-reef/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;Krabber stores everything in one DynamoDB table. Accounts, molts, replies, likes, follows, the home feed, notifications, sessions, and the rate-limit counters all live together in a table literally named &lt;code&gt;krabber-prod&lt;/code&gt;. No Postgres, no Redis, no separate store for sessions. Just one table.&lt;/p&gt;
&lt;p&gt;People hear &amp;ldquo;single-table design&amp;rdquo; and picture some kind of magic trick. It isn&amp;rsquo;t. It&amp;rsquo;s really just a few boring rules applied consistently, and in this post I want to walk through the ones that matter so you could do the same on your next project. This is the data model half of the story; the &lt;a href="https://t0ul.com/blog/metering-every-request-dynamodb-cost/"&gt;cost post&lt;/a&gt; is its companion.&lt;/p&gt;</description></item><item><title>How Krabber runs: one box, one table, no framework</title><link>https://t0ul.com/blog/how-krabber-runs/</link><pubDate>Thu, 20 Oct 2022 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/how-krabber-runs/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;Krabber is my Go port of &lt;a href="https://github.com/crabber-net/crabber"&gt;Crabber&lt;/a&gt;, a Python and Flask clone of Twitter. I built my own take on it in Go, kept it under the same open-source license, and credited the original. I&amp;rsquo;ve spun krabber.net up and down over the years since, mostly because I just enjoy the exercise of running a small, real service end to end.&lt;/p&gt;</description></item><item><title>Why I put Krabber on Elastic Beanstalk, not Lambda</title><link>https://t0ul.com/blog/why-beanstalk-not-lambda/</link><pubDate>Thu, 14 Jul 2022 00:00:00 +0000</pubDate><guid>https://t0ul.com/blog/why-beanstalk-not-lambda/</guid><description>&lt;p&gt;&lt;em&gt;Part of my &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt; series, a Twitter clone in Go. The full source is &lt;a href="https://github.com/t0ul/krabber-net"&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;When you build a small web app in 2026, the reflex answer is &amp;ldquo;throw it on Lambda.&amp;rdquo; Serverless, scale to zero, pay per request. And for a lot of things that&amp;rsquo;s the right call. But when I shipped &lt;a href="https://t0ul.com/projects/krabber/"&gt;Krabber&lt;/a&gt;, my Twitter clone, I put it on a single Elastic Beanstalk instance instead, and I want to walk through why, because the reasoning is the interesting part, not the YAML.&lt;/p&gt;</description></item></channel></rss>