Skip to main content

10 posts tagged with "architecture"

View All Tags

One event, four destinations: how notifications fan out

· 9 min read

Your Genie finishes a long edit while you're staring at a different tab. Three things should happen at once: a toast slides in, a new item lands in your inbox so the news survives a reload, and — if you asked for it — your phone buzzes. None of the code that produced that message knows any of this. It raised one notification, passed a player and a string, and moved on.

That gap — between "something happened" and "the user finds out, in four different places" — is the small piece of the system that taught us the most about keeping a Rails app real-time.

Cascades and the edges that deliberately do not exist

· 10 min read

Most of the time, the dangerous question in a distributed system isn't "what does this delete cascade to?" It's "what does it not cascade to — and are you sure?"

We spend a lot of energy reasoning about the edges that do fire: delete a Marquee, and a chain of consequences unfolds. But the bugs that wake you at 3am are usually the opposite shape. Someone toggles an innocuous setting — disables a Prop, edits a Secret, demotes a teammate — and a long-running environment they didn't mean to touch quietly falls over. The edge that surprised them is one nobody designed; it emerged because some well-meaning "keep things in sync on every save" hook reached one relationship too far.

One 402 to rule them all: the not-funded gate

· 6 min read

Every platform that rents compute eventually asks the same question in a hundred different places: is this allowed to run right now? On Fibe, "right now" means funded — a Marquee that has paid for the current service-day. We answer that question with exactly one check and one HTTP status, and we route the consequences differently depending on who's asking.

This is the story of the not-funded gate — a single 402 that sits in front of roughly a hundred call sites.

One Subscription, three payment providers

· 9 min read

Most of our billing code does not know which payment provider charged the card. That is on purpose, and one of our better early decisions.

Fibe takes money through three processors — Stripe, Creem, and Paddle — but the rest of the platform sees exactly one thing: a subscription record and a paid order. The provider name is just a stored string. Everything downstream — minting Mana, provisioning a tutorial Marquee, converting to Sparks, the daily funding sweep that keeps your environment alive — reads from that neutral layer and never branches on "is this Stripe or Paddle." Here's how, and why it earns its keep.

Six Genie providers behind one interface

· 10 min read

A Genie is an AI coding agent that lives next to your code. On Fibe you spin one up, it gets its own subdomain, and you talk to it in a pane in the browser. Behind that pane is a Docker Compose project running as a sidecar on your Marquee. The interesting part is that the same machinery runs Gemini, Antigravity, Claude Code, OpenAI Codex, Cursor, and OpenCode — six providers with six different CLIs, six different credential layouts, and six different opinions about how authentication should work — and the runtime that deploys them does not know, or care, which one it just shipped.

That last sentence is the whole design. When you can add a coding agent without touching the deploy pipeline, the reconciler, or the healthcheck, adding the seventh provider stops being a project and becomes an afternoon.

The polyglot stack behind Fibe: Rails, a Rust core, a NestJS genie, and a Go SDK

· 21 min read

People assume four languages means four teams who couldn't agree, or four phases of a rewrite that never finished. Neither is true here. Fibe speaks Ruby, Rust, TypeScript, and Go on purpose, and each one is doing a job the others would do worse. The interesting part isn't the list — every grown-up system has a list. It's the rule that decides which language a given function lands in, and how boring we kept the seams between them.

This post is the honest version: what each piece is, why it exists, and the trade-offs we swallowed to get here. If you've ever stared at a monolith and wondered when to carve a piece off — and into what — this is one team's answer.

Keeping a Rails monolith modular with Packwerk

· 10 min read

Every few months someone asks when Fibe is going to "break the monolith into services." It's a reasonable question. We provision Docker hosts, route TLS, run AI coding agents, charge money, and reconcile container state every sixty seconds — all in one Rails app that ships in one deploy. On paper, the thing the microservices talks warn you about.

It isn't, and the reason is boring in the best way: the monolith is split into ten-plus enforced domains whose boundaries are checked in CI, so a call from the billing domain into the provisioning domain's internals fails the build like a syntax error would. We get the part of microservices that matters — domains that can't secretly reach into each other — and skip the part that hurts: a network between every method call.

Props: one Git binding feeding every dynamic service

· 10 min read

Early on, Fibe passed repository URLs around like loose change. A Playground needed source, so it took a URL. An image build took a URL — and a token, and a branch, and a guess about which provider this was and how to authenticate. Every place that touched a Git repo re-derived the same three or four facts, and every place got to be wrong in its own way.

So we stopped. A repo became a resource you bind once and reuse: a Prop. Clone it for a Playground, build an image from it, fire a headless Trick when it changes — all from the same binding, with auth resolved in one place. Here's why that's a real model, not just a wrapper around a string.

Why we carved a Rust core out of our Rails app

· 10 min read

Fibe has been a Rails monolith since the first commit, and after a couple of years running a Docker-based dev-environment platform on it, we still think that was the right call. So when a small Rust workspace showed up in the repo, the obvious question — including from across the team — was some flavor of "oh no, are we rewriting in Rust?"

No. We extracted a very specific, very boring slice of the codebase into Rust, behind a rule we can state in one sentence. This post is that rule, why it works, and the genuinely annoying parts.

How Fibe works: a tour of the whole platform

· 24 min read

The first time someone watches a Fibe environment come up, the question is always the same: where is this thing actually running? You clicked a button, a URL appeared, and thirty seconds later you had a full-stack app with its own subdomain and a valid TLS cert. No docker run, no DNS records, no certbot. It feels like magic, and magic is exactly the kind of thing engineers distrust.

So let's pull the curtain back. This post is the map of the whole platform — the nouns, how they fit together, and the literal sequence of events between "click Launch" and "your app is live." If you read one thing about how Fibe is built, read this; the rest of the blog drills into the corners.