| 1 | # π€ How the carbon compares |
| 2 | |
| 3 | The third leg of the comparison series β the siblings are |
| 4 | [comparison.md](comparison.md) (the product) and |
| 5 | [comparison-infrastructure.md](comparison-infrastructure.md) (the |
| 6 | architecture's prior art). This one estimates what the |
| 7 | [#550 architecture](https://github.com/elevenmessenger/messenger/issues/550) |
| 8 | β one hibernating single-binary instance per space, state parked in S3 as |
| 9 | ciphertext β costs the planet at scale, against the conventional |
| 10 | alternative: a multi-tenant Rails monolith on a Kubernetes fleet with a big |
| 11 | always-on database tier. |
| 12 | |
| 13 | The short version: at a million spaces (~10M members), the Eleven model |
| 14 | works out to roughly **10β50Γ more carbon-efficient**, central estimate |
| 15 | **~30Γ** β on the order of **2 g COβe per member per year** against ~75 g |
| 16 | for the conventional stack. The headline mechanism isn't any one trick: |
| 17 | it's that a compiled binary, in-process SQLite, scale-to-zero hibernation, |
| 18 | no control plane, and E2EE-foreclosed server work *multiply*. |
| 19 | |
| 20 | Everything here is a Fermi estimate with Β±2β3Γ error bars, and the |
| 21 | absolute numbers are softer than the ratio β most of the uncertainties |
| 22 | (grid intensity, PUE, utilization assumptions) hit both sides and cancel. |
| 23 | The inputs are real, though: the Eleven side starts from live measurements |
| 24 | of the production fleet. |
| 25 | |
| 26 | ## The measured starting point (production box, 2026-07-11) |
| 27 | |
| 28 | The entire Eleven production β 15 running instances (every real space plus |
| 29 | canaries), the router, all four sibling services (home, push relay, connect |
| 30 | broker, cloud provisioner), and five AI bot sidecars β measured live: |
| 31 | |
| 32 | | what | measured | |
| 33 | |---|---| |
| 34 | | A warm instance (whole app: server, DB engine, frontend) | **20β28 MB RSS**, avg ~23 MB | |
| 35 | | Router + all four sibling services | ~110 MB combined | |
| 36 | | A Go bot sidecar | ~18 MB | |
| 37 | | **The whole fleet** | **~550 MB RAM, load average 0.21 on 2 ARM vCPUs** | |
| 38 | | Hibernated instances (7 of 22 on disk at measurement time) | **0 MB, 0 CPU** | |
| 39 | | A space's entire E2EE history (SQLite ciphertext) | 1β16 MB | |
| 40 | |
| 41 | That last table row pair is the whole story in miniature: the marginal cost |
| 42 | of a *sleeping* space is a few megabytes of object storage, and the |
| 43 | marginal cost of an *awake* one is ~23 MB of RAM and almost no CPU. Today's |
| 44 | entire production draws a single-digit-watt slice of one shared server β |
| 45 | less than a nightlight. |
| 46 | |
| 47 | ## The scenario: 1M spaces, ~10M members |
| 48 | |
| 49 | The anchor scale is the #550 plan's own 1M-space column. Coefficients are |
| 50 | from the [Cloud Carbon Footprint](https://www.cloudcarbonfootprint.org/docs/methodology/) |
| 51 | methodology (~2 Wh per vCPU-hour at typical utilization, ~0.39 W per GB of |
| 52 | RAM, ~1 Wh/TB-hour for replicated object storage), AWS's published fleet |
| 53 | PUE of ~1.15, and a location-based grid intensity of 350 g COβe/kWh |
| 54 | (between the IEA global average of ~480 and typical European cloud |
| 55 | regions; sensitivity discussed below). |
| 56 | |
| 57 | ### The Eleven fleet |
| 58 | |
| 59 | | assumption | value | basis | |
| 60 | |---|---|---| |
| 61 | | Spaces awake at any moment | ~10% (range 5β20%) | group chats are bursty; hibernation on idle | |
| 62 | | Warm set | 100k Γ ~25 MB β 2.5 TB active RAM; provision ~6 TB | measured RSS | |
| 63 | | Messages | 10M members Γ 100/day β 12k msg/s average | generous | |
| 64 | | 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) | |
| 65 | | Space state | ~15 TB of SQLite ciphertext in S3 | measured 1β16 MB per space | |
| 66 | | Attachments | ~100 TB on zero-egress object storage | the plan's figure | |
| 67 | |
| 68 | Power: CPU 1,000 vCPU Γ 2 Wh/h β 2.0 kW; RAM 6,000 GB Γ 0.39 W β 2.4 kW; |
| 69 | object storage (both buckets, 3Γ replicated) β 0.3 kW; NLB, activator, |
| 70 | sibling services, network β +15%. Times PUE 1.15: |
| 71 | |
| 72 | **β 6 kW continuous** (range 3β12 kW) β ~53 MWh/yr β **~18 t COβe/yr |
| 73 | operational**. Embodied carbon: this is only ~8β10 physical servers' |
| 74 | worth of hardware plus a slice of the storage fleet β ~4 t/yr amortized |
| 75 | over a 5-year life. **Total β 22 t COβe/yr β 2 g per member per year**, |
| 76 | or about **0.5 joules of server energy per message**. |
| 77 | |
| 78 | ### The conventional comparator |
| 79 | |
| 80 | The best public calibration point for a Rails fleet is |
| 81 | [37signals' cloud exit](https://world.hey.com/dhh/the-hardware-we-need-for-our-cloud-exit-has-arrived-99d66966): |
| 82 | ~4,000 vCPUs and ~7.7 TB of RAM of purchased hardware to run Basecamp + |
| 83 | HEY β order 1β2M users β and that's a famously *lean* shop (Kamal, no |
| 84 | Kubernetes, tight packing). Scaled to 10M users: ~20,000 vCPUs, ~40 TB |
| 85 | RAM, roughly **75β100 kW**. |
| 86 | |
| 87 | A *typical* multi-tenant Kubernetes deployment is materially heavier than |
| 88 | that baseline. Industry container surveys (Datadog's container reports) |
| 89 | put actually-used CPU at ~20β30% of requested; on top sit the control |
| 90 | plane, service-mesh sidecars, the observability fleet (metrics, logging, |
| 91 | tracing β commonly 10β20% of nodes), staging environments, and an |
| 92 | always-on HA Postgres + Redis + search tier provisioned for peak with no |
| 93 | scale-to-zero anywhere in the stack. That lands at **~150β300 kW** β |
| 94 | call it 200 kW central: |
| 95 | |
| 96 | **β 200 kW** β ~1,750 MWh/yr β ~615 t operational + ~150 t/yr embodied |
| 97 | (order 500 servers) β **~750 t COβe/yr β 75 g per member per year**, or |
| 98 | roughly **20β30 joules per message**. |
| 99 | |
| 100 | ### The ratio |
| 101 | |
| 102 | | comparator | ratio | |
| 103 | |---|---| |
| 104 | | A lean Rails shop (37signals-grade, no K8s) | ~10β15Γ | |
| 105 | | A typical enterprise K8s deployment | ~30β60Γ | |
| 106 | | **Central estimate** | **~30Γ** | |
| 107 | |
| 108 | ## Where the ~30Γ comes from |
| 109 | |
| 110 | The advantage is multiplicative across mostly-independent factors β which |
| 111 | is why it's large, and why no single optimization on the Rails side closes |
| 112 | the gap: |
| 113 | |
| 114 | | factor | ~multiplier | why | |
| 115 | |---|---|---| |
| 116 | | 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 | |
| 117 | | 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 | |
| 118 | | 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 | |
| 119 | | 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 | |
| 120 | | 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 | |
| 121 | |
| 122 | The last row is the quiet one: E2EE is usually costed as a *constraint*. |
| 123 | In carbon terms it's a subsidy β every feature the server can't see is a |
| 124 | feature the server can't burn watts computing. |
| 125 | |
| 126 | ## What this estimate is not |
| 127 | |
| 128 | Honesty section, in the spirit of the siblings: |
| 129 | |
| 130 | - **Hibernation is the entire trick.** The marginal cost of an *idle* |
| 131 | tenant actually favors multi-tenant β kilobytes of Postgres rows versus |
| 132 | ~23 MB warm. Process-per-tenant *without* scale-to-zero would be worse |
| 133 | than Rails, not better. If duty cycle approached 100%, the advantage |
| 134 | shrinks toward just the runtime factor (~5β10Γ). |
| 135 | - **Grid intensity can dominate everything.** A Rails app on a |
| 136 | market-based-zero renewable contract versus this stack on a coal grid |
| 137 | inverts the operational numbers. Embodied carbon β ~10 servers versus |
| 138 | ~500 β favors the small fleet regardless of who signs which PPA. |
| 139 | - **Runtime AI inference isn't counted in the ratio.** Heavy LLM use by the |
| 140 | bot sidecars would dwarf either infrastructure's footprint β and applies to |
| 141 | both models equally, so it cancels out of *this comparison's* ratio and |
| 142 | dominates the absolutes. (It is at least *measurable* exactly: the sidecars |
| 143 | run on an API key, so the provider console has precise token counts.) The |
| 144 | live status-page **run** estimate does carry a small, bounded inference term |
| 145 | (see *The status page*), and the AI cost of *building* the app is estimated |
| 146 | in full β see the next section. |
| 147 | - **Client-side work moves joules, it doesn't create many.** Crypto and |
| 148 | image downscaling run on members' devices; the marginal energy per |
| 149 | message on a phone is micro-joules against a battery already being |
| 150 | spent on the screen. |
| 151 | - **The comparator is a plain chat app.** A real product messenger with |
| 152 | search, analytics, growth infrastructure, and data pipelines would widen |
| 153 | the gap further; this comparison deliberately gives Rails the benefit of |
| 154 | doing only what Eleven does. |
| 155 | |
| 156 | ## What the AI that built it cost |
| 157 | |
| 158 | The estimates above stop at the servers. But this codebase is AI-written, |
| 159 | and the honest ledger has to include the tokens it took to write it β which |
| 160 | turn out to dwarf, by orders of magnitude, the infrastructure they produced |
| 161 | (at today's scale; at the 1M-space scale above, the fleet takes over). |
| 162 | |
| 163 | **The tokens are measurable.** Claude Code keeps per-session transcripts |
| 164 | with exact token counts. Summed over every session against this repo on the |
| 165 | primary dev machine (the first measurement, 2026-07-03 β 2026-07-11, 162 |
| 166 | sessions β transcripts from the repo's first week, 2026-06-27 β 07-02, had |
| 167 | already been auto-pruned, so that week is extrapolated from the measured |
| 168 | window's per-commit rate): |
| 169 | |
| 170 | | | tokens | |
| 171 | |---|---| |
| 172 | | Output (generated text + code) | **~25M measured + ~9M extrapolated β 34M** | |
| 173 | | Fresh input (prompt prefill) | ~145M measured | |
| 174 | | Cache reads | ~7.9B measured | |
| 175 | |
| 176 | **The conversion is the soft part.** No frontier lab publishes per-token |
| 177 | energy or carbon. The best public calibration points disagree by ~30Γ: |
| 178 | Google's production study of Gemini serving works out to roughly 0.1 mg |
| 179 | COβe per output token, while Mistral's lifecycle study for Large 2 implies |
| 180 | ~2.9 mg. We band with **0.1β3 mg COβe per output token, central 0.55 mg** |
| 181 | (the geometric mean), priced on output tokens only β decode dominates |
| 182 | serving energy, and nobody publishes a price for cached prefill, which is |
| 183 | ~97% of tokens processed here. That un-priced cache-read pile, plus |
| 184 | cloud-side agent runs and any contributor machine that hasn't accrued its |
| 185 | entries yet, make this a floor. |
| 186 | |
| 187 | **Result so far: ~6β180 kg COβe, central ~34 kg.** To make that legible, |
| 188 | the status page renders the central estimate as a set of everyday anchors |
| 189 | (each factor documented under *What the anchors mean* below): about **half a |
| 190 | DublinβLondon economy flight**, **~15 hours** of a petrol leaf blower, |
| 191 | **~0.6 kg of beef**, and **~1.6 tree-years** to soak it back up β or **~200 |
| 192 | km** in a petrol car (~15 litres). E2EE keeps the *servers* from burning |
| 193 | watts on members' content; the watts moved upstream, into the model that |
| 194 | wrote the code. |
| 195 | |
| 196 | **This number accrues, so it's kept as a running tally**: the ledger lives |
| 197 | in [`web/status/carbon.json`](../web/status/carbon.json) and publishes with |
| 198 | the public dashboards at |
| 199 | [status.elevenmessenger.com/carbon.html](https://status.elevenmessenger.com/carbon.html) |
| 200 | (cumulative chart + per-period ledger; `docs/status.md`). It covers **every |
| 201 | contributor machine**, each accruing entries under an anonymous stable |
| 202 | `source` label, and **keeping it up to date is automated**: a `SessionStart` |
| 203 | hook nudges any Claude session in this repo when its machine's entries go |
| 204 | stale (the transcripts it measures from are pruned after about a week), and |
| 205 | `node tools/carbon-tally.mjs --write` appends only what's newer than that |
| 206 | machine's last entry β recipe in `docs/status.md Β§ Keeping the carbon tally |
| 207 | accruing`. A gap that slips past the pruning window gets an |
| 208 | explicitly-flagged `extrapolated` entry, like the first week did. |
| 209 | |
| 210 | ## The status page: two figures, built and run |
| 211 | |
| 212 | The public page carries **two** ledgers, deliberately separate and neither |
| 213 | editorialised against the other: |
| 214 | |
| 215 | - **Built** β the one-time AI cost of *making* the app (the tally above). It |
| 216 | grows only when more AI development happens. |
| 217 | - **Run** β the ongoing cost of *operating* the whole fleet, recomputed live |
| 218 | at every publish. It rises with the fleet β one box today, fifty later. |
| 219 | |
| 220 | They are two different things β *one-time to make* versus *ongoing to |
| 221 | operate, and rising with scale* β so the page does **not** claim one is |
| 222 | "bigger" than the other; the ratio between them is a moving target that says |
| 223 | more about how young and how small the fleet is than about either number. |
| 224 | The figure that stays meaningful at any size is the **per-space** run rate. |
| 225 | |
| 226 | **The run estimate, banded low/central/high.** Computed at publish time in |
| 227 | `deploy/status-publish.sh` (`carbon_run_object`), summing every service the |
| 228 | stack needs: |
| 229 | |
| 230 | 1. **The router box + its instances.** The Hetzner Cloud API gives each |
| 231 | server's `server_type` (its vCPU count); the whole fleet is a lightly |
| 232 | loaded, hibernating workload (load ~0.2 on the box), so its attributable |
| 233 | draw is a **low-single-digit-to-~15 W slice** of the box, modelled as |
| 234 | **per-vCPU average watts β 1.5 / 3.5 / 7.5 W** (marginal load-proportional |
| 235 | β whole-box idle-inclusive). Times **24 h**, times the **box region's grid |
| 236 | intensity**, times **PUE β 1.15**. The prod box is in **Helsinki, so the |
| 237 | Finnish grid β 80β130 g COβe/kWh** (a low-carbon, hydro/nuclear/wind mix); |
| 238 | the low band takes the grid to **β 0** (Hetzner's EU sites run on a |
| 239 | renewable-electricity contract), the high band to the location grid. vCPUs |
| 240 | sum across every box in the account, so the term scales as boxes are added. |
| 241 | 2. **Object storage (AWS).** Our S3 use is a slice of ciphertext plus |
| 242 | requests β near-zero, but stated as a **small explicit banded term** |
| 243 | (~a gram a day), never folded to zero. |
| 244 | 3. **Bot inference.** The sidecars' ongoing Anthropic API use. Small today |
| 245 | and **bounded wide** (the high band allows for busy days); precise token |
| 246 | counts exist in the provider console, but the page publishes a bounded |
| 247 | estimate rather than couple to a live spend feed. |
| 248 | |
| 249 | The result publishes as a **daily rate**, a **cumulative-to-date** (the daily |
| 250 | rate Γ days since the fleet's start β a first-order figure that assumes |
| 251 | today's rate held), and **per active space** (denominator = the public |
| 252 | instance count from the registry β **never** per-member, no member counts). |
| 253 | At today's single box that lands at **tens of grams of COβe per day** for the |
| 254 | whole fleet β less than a nightlight β and a per-space rate of a **gram or so |
| 255 | per space per day**. All coefficients are honest bands, and the region grid |
| 256 | is the one that can dominate everything (see below). |
| 257 | |
| 258 | ## What the anchors mean |
| 259 | |
| 260 | The everyday equivalents shown beside **both** figures (each scaled to its |
| 261 | own magnitude β the build total, and the run's cumulative-to-date) convert |
| 262 | the central kg through published, banded factors. Snapshot **July 2026**; |
| 263 | these move, so re-check before quoting. |
| 264 | |
| 265 | | anchor | factor (central) | band | source class | |
| 266 | |---|---|---|---| |
| 267 | | Petrol car | 170 g COβe/km; 1 L petrol β 2.3 kg | Β±~15% | DEFRA/EPA average passenger car | |
| 268 | | **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 | |
| 269 | | **Leaf blower** | 2-stroke ~1 L/h β **~2.3 kg COβ/h** | Β±~25% | EPA small-engine fuel burn Γ petrol EF | |
| 270 | | **Beef** | **~60 kg COβe/kg** (land-use-inclusive) | 40β100 | Poore & Nemecek (Science 2018) / Our World in Data | |
| 271 | | **Tree-years** | a mature tree absorbs **~21 kg COβ/yr** | 10β40 | EPA / arboricultural estimates | |
| 272 | |
| 273 | The flight is expressed against **one real short leg β DublinβLondon |
| 274 | (DUBβLHR) β 460 km great-circle β β 67 kg COβe per economy leg** β so "half a |
| 275 | DublinβLondon flight" is ~34 kg. The uplift matters: without the |
| 276 | radiative-forcing multiplier the same leg is ~40% lower, so the page names it |
| 277 | explicitly. Distances and volumes convert with the metric/imperial toggle; |
| 278 | the mass anchors (beef) convert too; counts and durations (flights, |
| 279 | leaf-blower time, tree-years) are unit-agnostic. |
| 280 | |
| 281 | ## The one-sentence version |
| 282 | |
| 283 | **~2 g versus ~75 g COβe per member per year β the difference between an |
| 284 | infrastructure that sleeps when its members do, and one that idles at peak |
| 285 | provisioning forever.** |
| 286 | |
| 287 | ## Sources |
| 288 | |
| 289 | - [Cloud Carbon Footprint β methodology & coefficients](https://www.cloudcarbonfootprint.org/docs/methodology/) |
| 290 | - [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) |
| 291 | - [Pereira et al., *Energy Efficiency across Programming Languages* (SLE 2017)](https://greenlab.di.uminho.pt/wp-content/uploads/2017/10/sleFinal.pdf) |
| 292 | - [Datadog Container Report β utilization findings](https://www.datadoghq.com/container-report/) |
| 293 | - [AWS sustainability β fleet PUE](https://sustainability.aboutamazon.com/products-services/aws-cloud) |
| 294 | - [IEA β global electricity carbon intensity](https://www.iea.org/energy-system/electricity) |
| 295 | - [Electricity Maps β Finland grid carbon intensity](https://app.electricitymaps.com/zone/FI) (the prod box's Helsinki region; ~80β130 g COβe/kWh) |
| 296 | - Everyday anchors (all snapshot July 2026, banded): |
| 297 | [DEFRA/DESNZ greenhouse-gas conversion factors](https://www.gov.uk/government/collections/government-conversion-factors-for-company-reporting) |
| 298 | (average car ~0.17 kg COβe/km, petrol ~2.31 kg/L, short-haul economy air |
| 299 | ~0.15 kg COβe/pax-km with radiative forcing); |
| 300 | [Poore & Nemecek, *Reducing food's environmental impacts* (Science 2018)](https://www.science.org/doi/10.1126/science.aaq0216) |
| 301 | via [Our World in Data](https://ourworldindata.org/environmental-impacts-of-food) |
| 302 | (beef ~60 kg COβe/kg, land-use-inclusive); |
| 303 | [US EPA β greenhouse gas equivalencies](https://www.epa.gov/energy/greenhouse-gases-equivalencies-calculator-calculations-and-references) |
| 304 | (a mature tree ~21 kg COβ/yr; small-engine fuel burn) |
| 305 | - [Google Cloud β measuring the environmental impact of AI inference](https://cloud.google.com/blog/products/infrastructure/measuring-the-environmental-impact-of-ai-inference) |
| 306 | - [Mistral AI β lifecycle analysis of Large 2](https://mistral.ai/news/our-contribution-to-a-global-environmental-standard-for-ai) |
| 307 | - [Epoch AI β how much energy does ChatGPT use?](https://epoch.ai/gradient-updates/how-much-energy-does-chatgpt-use) |
| 308 | - [EcoLogits β provider-side LLM impact methodology](https://ecologits.ai/) |
| 309 | - Live fleet measurements: production router box, 2026-07-11 (per-unit |
| 310 | RSS via systemd; 15 warm instances + 4 services + 5 sidecars β 550 MB, |
| 311 | load 0.21 on 2 ARM vCPUs) |
| 312 | - Build-token measurements: local Claude Code transcripts, swept by |
| 313 | `tools/carbon-tally.mjs` into `web/status/carbon.json` (the running tally) |
| 314 | - The plan: [#550 β planet-scale over S3](https://github.com/elevenmessenger/messenger/issues/550) |
| 315 | |
| 316 | *Snapshot as of July 2026 β coefficients and grids move; re-measure before |
| 317 | quoting.* |
| 318 | |