# 🤖 How the carbon compares

The third leg of the comparison series — the siblings are
[comparison.md](comparison.md) (the product) and
[comparison-infrastructure.md](comparison-infrastructure.md) (the
architecture's prior art). This one estimates what the
[#550 architecture](https://github.com/elevenmessenger/messenger/issues/550)
— one hibernating single-binary instance per space, state parked in S3 as
ciphertext — costs the planet at scale, against the conventional
alternative: a multi-tenant Rails monolith on a Kubernetes fleet with a big
always-on database tier.

The short version: at a million spaces (~10M members), the Eleven model
works out to roughly **10–50× more carbon-efficient**, central estimate
**~30×** — on the order of **2 g CO₂e per member per year** against ~75 g
for the conventional stack. The headline mechanism isn't any one trick:
it's that a compiled binary, in-process SQLite, scale-to-zero hibernation,
no control plane, and E2EE-foreclosed server work *multiply*.

Everything here is a Fermi estimate with ±2–3× error bars, and the
absolute numbers are softer than the ratio — most of the uncertainties
(grid intensity, PUE, utilization assumptions) hit both sides and cancel.
The inputs are real, though: the Eleven side starts from live measurements
of the production fleet.

## The measured starting point (production box, 2026-07-11)

The entire Eleven production — 15 running instances (every real space plus
canaries), the router, all four sibling services (home, push relay, connect
broker, cloud provisioner), and five AI bot sidecars — measured live:

| what | measured |
|---|---|
| A warm instance (whole app: server, DB engine, frontend) | **20–28 MB RSS**, avg ~23 MB |
| Router + all four sibling services | ~110 MB combined |
| A Go bot sidecar | ~18 MB |
| **The whole fleet** | **~550 MB RAM, load average 0.21 on 2 ARM vCPUs** |
| Hibernated instances (7 of 22 on disk at measurement time) | **0 MB, 0 CPU** |
| A space's entire E2EE history (SQLite ciphertext) | 1–16 MB |

That last table row pair is the whole story in miniature: the marginal cost
of a *sleeping* space is a few megabytes of object storage, and the
marginal cost of an *awake* one is ~23 MB of RAM and almost no CPU. Today's
entire production draws a single-digit-watt slice of one shared server —
less than a nightlight.

## The scenario: 1M spaces, ~10M members

The anchor scale is the #550 plan's own 1M-space column. Coefficients are
from the [Cloud Carbon Footprint](https://www.cloudcarbonfootprint.org/docs/methodology/)
methodology (~2 Wh per vCPU-hour at typical utilization, ~0.39 W per GB of
RAM, ~1 Wh/TB-hour for replicated object storage), AWS's published fleet
PUE of ~1.15, and a location-based grid intensity of 350 g CO₂e/kWh
(between the IEA global average of ~480 and typical European cloud
regions; sensitivity discussed below).

### The Eleven fleet

| assumption | value | basis |
|---|---|---|
| Spaces awake at any moment | ~10% (range 5–20%) | group chats are bursty; hibernation on idle |
| Warm set | 100k × ~25 MB ≈ 2.5 TB active RAM; provision ~6 TB | measured RSS |
| Messages | 10M members × 100/day ≈ 12k msg/s average | generous |
| CPU | a few hundred vCPUs busy; ~1,000 provisioned | ~1–5 ms CPU per message incl. WS fan-out; RAM, not CPU, is the binding constraint (the live box serves everything at load 0.2) |
| Space state | ~15 TB of SQLite ciphertext in S3 | measured 1–16 MB per space |
| Attachments | ~100 TB on zero-egress object storage | the plan's figure |

Power: CPU 1,000 vCPU × 2 Wh/h ≈ 2.0 kW; RAM 6,000 GB × 0.39 W ≈ 2.4 kW;
object storage (both buckets, 3× replicated) ≈ 0.3 kW; NLB, activator,
sibling services, network ≈ +15%. Times PUE 1.15:

**≈ 6 kW continuous** (range 3–12 kW) → ~53 MWh/yr → **~18 t CO₂e/yr
operational**. Embodied carbon: this is only ~8–10 physical servers'
worth of hardware plus a slice of the storage fleet — ~4 t/yr amortized
over a 5-year life. **Total ≈ 22 t CO₂e/yr ≈ 2 g per member per year**,
or about **0.5 joules of server energy per message**.

### The conventional comparator

The best public calibration point for a Rails fleet is
[37signals' cloud exit](https://world.hey.com/dhh/the-hardware-we-need-for-our-cloud-exit-has-arrived-99d66966):
~4,000 vCPUs and ~7.7 TB of RAM of purchased hardware to run Basecamp +
HEY — order 1–2M users — and that's a famously *lean* shop (Kamal, no
Kubernetes, tight packing). Scaled to 10M users: ~20,000 vCPUs, ~40 TB
RAM, roughly **75–100 kW**.

A *typical* multi-tenant Kubernetes deployment is materially heavier than
that baseline. Industry container surveys (Datadog's container reports)
put actually-used CPU at ~20–30% of requested; on top sit the control
plane, service-mesh sidecars, the observability fleet (metrics, logging,
tracing — commonly 10–20% of nodes), staging environments, and an
always-on HA Postgres + Redis + search tier provisioned for peak with no
scale-to-zero anywhere in the stack. That lands at **~150–300 kW** —
call it 200 kW central:

**≈ 200 kW** → ~1,750 MWh/yr → ~615 t operational + ~150 t/yr embodied
(order 500 servers) ≈ **~750 t CO₂e/yr ≈ 75 g per member per year**, or
roughly **20–30 joules per message**.

### The ratio

| comparator | ratio |
|---|---|
| A lean Rails shop (37signals-grade, no K8s) | ~10–15× |
| A typical enterprise K8s deployment | ~30–60× |
| **Central estimate** | **~30×** |

## Where the ~30× comes from

The advantage is multiplicative across mostly-independent factors — which
is why it's large, and why no single optimization on the Rails side closes
the gap:

| factor | ~multiplier | why |
|---|---|---|
| Runtime: compiled Go + in-process SQLite vs Ruby/Puma + network-hop DB | 4–8× | a Puma worker is 500 MB–1 GB vs ~23 MB for an *entire instance*; language-energy studies (Pereira et al., SLE 2017) put Ruby at ~20× Go on CPU-bound work |
| Scale-to-zero vs provision-for-peak | 2–4× | ~90% of spaces cost nothing at any moment; the multi-tenant fleet idles 24/7 at 20–30% utilization |
| No control plane / sidecars / observability tax | 1.3–1.7× | the "orchestrator" is an activator + an S3 lease — a rounding error, not a node pool |
| No hot database + cache + search tier | 1.5–2× | the database tier is often a third of a Rails fleet; here it's a file inside each process, and cold ones are parked ciphertext |
| E2EE forecloses server-side work | 1.2–2× | no indexing, analytics, ML pipelines, image proxying, or transcoding — structurally impossible, not just declined; even image downscaling happens on the client |

The last row is the quiet one: E2EE is usually costed as a *constraint*.
In carbon terms it's a subsidy — every feature the server can't see is a
feature the server can't burn watts computing.

## What this estimate is not

Honesty section, in the spirit of the siblings:

- **Hibernation is the entire trick.** The marginal cost of an *idle*
  tenant actually favors multi-tenant — kilobytes of Postgres rows versus
  ~23 MB warm. Process-per-tenant *without* scale-to-zero would be worse
  than Rails, not better. If duty cycle approached 100%, the advantage
  shrinks toward just the runtime factor (~5–10×).
- **Grid intensity can dominate everything.** A Rails app on a
  market-based-zero renewable contract versus this stack on a coal grid
  inverts the operational numbers. Embodied carbon — ~10 servers versus
  ~500 — favors the small fleet regardless of who signs which PPA.
- **Runtime AI inference isn't counted in the ratio.** Heavy LLM use by the
  bot sidecars would dwarf either infrastructure's footprint — and applies to
  both models equally, so it cancels out of *this comparison's* ratio and
  dominates the absolutes. (It is at least *measurable* exactly: the sidecars
  run on an API key, so the provider console has precise token counts.) The
  live status-page **run** estimate does carry a small, bounded inference term
  (see *The status page*), and the AI cost of *building* the app is estimated
  in full — see the next section.
- **Client-side work moves joules, it doesn't create many.** Crypto and
  image downscaling run on members' devices; the marginal energy per
  message on a phone is micro-joules against a battery already being
  spent on the screen.
- **The comparator is a plain chat app.** A real product messenger with
  search, analytics, growth infrastructure, and data pipelines would widen
  the gap further; this comparison deliberately gives Rails the benefit of
  doing only what Eleven does.

## What the AI that built it cost

The estimates above stop at the servers. But this codebase is AI-written,
and the honest ledger has to include the tokens it took to write it — which
turn out to dwarf, by orders of magnitude, the infrastructure they produced
(at today's scale; at the 1M-space scale above, the fleet takes over).

**The tokens are measurable.** Claude Code keeps per-session transcripts
with exact token counts. Summed over every session against this repo on the
primary dev machine (the first measurement, 2026-07-03 → 2026-07-11, 162
sessions — transcripts from the repo's first week, 2026-06-27 → 07-02, had
already been auto-pruned, so that week is extrapolated from the measured
window's per-commit rate):

| | tokens |
|---|---|
| Output (generated text + code) | **~25M measured + ~9M extrapolated ≈ 34M** |
| Fresh input (prompt prefill) | ~145M measured |
| Cache reads | ~7.9B measured |

**The conversion is the soft part.** No frontier lab publishes per-token
energy or carbon. The best public calibration points disagree by ~30×:
Google's production study of Gemini serving works out to roughly 0.1 mg
CO₂e per output token, while Mistral's lifecycle study for Large 2 implies
~2.9 mg. We band with **0.1–3 mg CO₂e per output token, central 0.55 mg**
(the geometric mean), priced on output tokens only — decode dominates
serving energy, and nobody publishes a price for cached prefill, which is
~97% of tokens processed here. That un-priced cache-read pile, plus
cloud-side agent runs and any contributor machine that hasn't accrued its
entries yet, make this a floor.

**Result so far: ~6–180 kg CO₂e, central ~34 kg.** To make that legible,
the status page renders the central estimate as a set of everyday anchors
(each factor documented under *What the anchors mean* below): about **half a
Dublin–London economy flight**, **~15 hours** of a petrol leaf blower,
**~0.6 kg of beef**, and **~1.6 tree-years** to soak it back up — or **~200
km** in a petrol car (~15 litres). E2EE keeps the *servers* from burning
watts on members' content; the watts moved upstream, into the model that
wrote the code.

**This number accrues, so it's kept as a running tally**: the ledger lives
in [`web/status/carbon.json`](../web/status/carbon.json) and publishes with
the public dashboards at
[status.elevenmessenger.com/carbon.html](https://status.elevenmessenger.com/carbon.html)
(cumulative chart + per-period ledger; `docs/status.md`). It covers **every
contributor machine**, each accruing entries under an anonymous stable
`source` label, and **keeping it up to date is automated**: a `SessionStart`
hook nudges any Claude session in this repo when its machine's entries go
stale (the transcripts it measures from are pruned after about a week), and
`node tools/carbon-tally.mjs --write` appends only what's newer than that
machine's last entry — recipe in `docs/status.md § Keeping the carbon tally
accruing`. A gap that slips past the pruning window gets an
explicitly-flagged `extrapolated` entry, like the first week did.

## The status page: two figures, built and run

The public page carries **two** ledgers, deliberately separate and neither
editorialised against the other:

- **Built** — the one-time AI cost of *making* the app (the tally above). It
  grows only when more AI development happens.
- **Run** — the ongoing cost of *operating* the whole fleet, recomputed live
  at every publish. It rises with the fleet — one box today, fifty later.

They are two different things — *one-time to make* versus *ongoing to
operate, and rising with scale* — so the page does **not** claim one is
"bigger" than the other; the ratio between them is a moving target that says
more about how young and how small the fleet is than about either number.
The figure that stays meaningful at any size is the **per-space** run rate.

**The run estimate, banded low/central/high.** Computed at publish time in
`deploy/status-publish.sh` (`carbon_run_object`), summing every service the
stack needs:

1. **The router box + its instances.** The Hetzner Cloud API gives each
   server's `server_type` (its vCPU count); the whole fleet is a lightly
   loaded, hibernating workload (load ~0.2 on the box), so its attributable
   draw is a **low-single-digit-to-~15 W slice** of the box, modelled as
   **per-vCPU average watts — 1.5 / 3.5 / 7.5 W** (marginal load-proportional
   → whole-box idle-inclusive). Times **24 h**, times the **box region's grid
   intensity**, times **PUE ≈ 1.15**. The prod box is in **Helsinki, so the
   Finnish grid ≈ 80–130 g CO₂e/kWh** (a low-carbon, hydro/nuclear/wind mix);
   the low band takes the grid to **≈ 0** (Hetzner's EU sites run on a
   renewable-electricity contract), the high band to the location grid. vCPUs
   sum across every box in the account, so the term scales as boxes are added.
2. **Object storage (AWS).** Our S3 use is a slice of ciphertext plus
   requests — near-zero, but stated as a **small explicit banded term**
   (~a gram a day), never folded to zero.
3. **Bot inference.** The sidecars' ongoing Anthropic API use. Small today
   and **bounded wide** (the high band allows for busy days); precise token
   counts exist in the provider console, but the page publishes a bounded
   estimate rather than couple to a live spend feed.

The result publishes as a **daily rate**, a **cumulative-to-date** (the daily
rate × days since the fleet's start — a first-order figure that assumes
today's rate held), and **per active space** (denominator = the public
instance count from the registry — **never** per-member, no member counts).
At today's single box that lands at **tens of grams of CO₂e per day** for the
whole fleet — less than a nightlight — and a per-space rate of a **gram or so
per space per day**. All coefficients are honest bands, and the region grid
is the one that can dominate everything (see below).

## What the anchors mean

The everyday equivalents shown beside **both** figures (each scaled to its
own magnitude — the build total, and the run's cumulative-to-date) convert
the central kg through published, banded factors. Snapshot **July 2026**;
these move, so re-check before quoting.

| anchor | factor (central) | band | source class |
|---|---|---|---|
| Petrol car | 170 g CO₂e/km; 1 L petrol ≈ 2.3 kg | ±~15% | DEFRA/EPA average passenger car |
| **Short-haul flight** | **0.145 kg CO₂e per economy passenger-km, incl. the non-CO₂ altitude uplift (~1.9× radiative forcing)** | **0.13–0.16** | DEFRA short-haul-with-RF economy class |
| **Leaf blower** | 2-stroke ~1 L/h → **~2.3 kg CO₂/h** | ±~25% | EPA small-engine fuel burn × petrol EF |
| **Beef** | **~60 kg CO₂e/kg** (land-use-inclusive) | 40–100 | Poore & Nemecek (Science 2018) / Our World in Data |
| **Tree-years** | a mature tree absorbs **~21 kg CO₂/yr** | 10–40 | EPA / arboricultural estimates |

The flight is expressed against **one real short leg — Dublin–London
(DUB–LHR) ≈ 460 km great-circle → ≈ 67 kg CO₂e per economy leg** — so "half a
Dublin–London flight" is ~34 kg. The uplift matters: without the
radiative-forcing multiplier the same leg is ~40% lower, so the page names it
explicitly. Distances and volumes convert with the metric/imperial toggle;
the mass anchors (beef) convert too; counts and durations (flights,
leaf-blower time, tree-years) are unit-agnostic.

## The one-sentence version

**~2 g versus ~75 g CO₂e per member per year — the difference between an
infrastructure that sleeps when its members do, and one that idles at peak
provisioning forever.**

## Sources

- [Cloud Carbon Footprint — methodology & coefficients](https://www.cloudcarbonfootprint.org/docs/methodology/)
- [37signals' cloud-exit hardware (4,000 vCPUs / 7.7 TB RAM)](https://world.hey.com/dhh/the-hardware-we-need-for-our-cloud-exit-has-arrived-99d66966)
- [Pereira et al., *Energy Efficiency across Programming Languages* (SLE 2017)](https://greenlab.di.uminho.pt/wp-content/uploads/2017/10/sleFinal.pdf)
- [Datadog Container Report — utilization findings](https://www.datadoghq.com/container-report/)
- [AWS sustainability — fleet PUE](https://sustainability.aboutamazon.com/products-services/aws-cloud)
- [IEA — global electricity carbon intensity](https://www.iea.org/energy-system/electricity)
- [Electricity Maps — Finland grid carbon intensity](https://app.electricitymaps.com/zone/FI) (the prod box's Helsinki region; ~80–130 g CO₂e/kWh)
- Everyday anchors (all snapshot July 2026, banded):
  [DEFRA/DESNZ greenhouse-gas conversion factors](https://www.gov.uk/government/collections/government-conversion-factors-for-company-reporting)
  (average car ~0.17 kg CO₂e/km, petrol ~2.31 kg/L, short-haul economy air
  ~0.15 kg CO₂e/pax-km with radiative forcing);
  [Poore & Nemecek, *Reducing food's environmental impacts* (Science 2018)](https://www.science.org/doi/10.1126/science.aaq0216)
  via [Our World in Data](https://ourworldindata.org/environmental-impacts-of-food)
  (beef ~60 kg CO₂e/kg, land-use-inclusive);
  [US EPA — greenhouse gas equivalencies](https://www.epa.gov/energy/greenhouse-gases-equivalencies-calculator-calculations-and-references)
  (a mature tree ~21 kg CO₂/yr; small-engine fuel burn)
- [Google Cloud — measuring the environmental impact of AI inference](https://cloud.google.com/blog/products/infrastructure/measuring-the-environmental-impact-of-ai-inference)
- [Mistral AI — lifecycle analysis of Large 2](https://mistral.ai/news/our-contribution-to-a-global-environmental-standard-for-ai)
- [Epoch AI — how much energy does ChatGPT use?](https://epoch.ai/gradient-updates/how-much-energy-does-chatgpt-use)
- [EcoLogits — provider-side LLM impact methodology](https://ecologits.ai/)
- Live fleet measurements: production router box, 2026-07-11 (per-unit
  RSS via systemd; 15 warm instances + 4 services + 5 sidecars ≈ 550 MB,
  load 0.21 on 2 ARM vCPUs)
- Build-token measurements: local Claude Code transcripts, swept by
  `tools/carbon-tally.mjs` into `web/status/carbon.json` (the running tally)
- The plan: [#550 — planet-scale over S3](https://github.com/elevenmessenger/messenger/issues/550)

*Snapshot as of July 2026 — coefficients and grids move; re-measure before
quoting.*
