eleven / messenger Public

Clone
git clone https://amadan.net/eleven/messenger

Plain git — no account needed to clone.

Download

Download this file

πŸ€– Tier economics β€” what a space costs us, what a space pays us

This is the public record of how Eleven's space-upgrade prices relate to what spaces actually cost to run. It exists because of a commitment made in #562: the price is the cost plus resilience, and that should be a checkable claim. When the public ledger ships (#550 Part 11), this document is the cost-model half of the books; until then it's the working version, re-derived whenever prices or input rates change.

Living doc: the formulas are the contract; the numbers are a snapshot (dated below). If you're reading this to make a decision, re-derive first.

Principles (decided in #562, held here)

  • Self-hosting is no-obligation. The paid thing is our hosting convenience, never the software. A self-hosted space owes nothing β€” and one that leans on shared glue we run (the push relay, the signed release feed) is warmly invited, never required, to contribute.
  • We can only price what ciphertext exposes: storage bytes, member counts, space counts. Never content, never analytics.
  • Paying is not anonymous. Checkout runs on Stripe, which collects a name, email, and card β€” and as the merchant we can see those in Stripe's dashboard. Our own stores still hold only two opaque Stripe ids, a tier key, and a period end per paid space, so a compromise of our systems exposes no billing identity.
  • The free tier is first-class. Constraints (storage quotas) ratchet later and only for new spaces; existing spaces keep what they have.
  • AI is never bundled β€” and off by default. Model tokens are the one marginal cost that can dwarf a subscription; bot/AI usage is always opt-in, and when opted into it's a metered add-on (design in #562).

The price book (as of 2026-07-22)

| Tier | Price | Billing | |---|---|---| | Family | €5.50/year | annual only | | Community & Friends | €0.11 per member per year, €11 minimum (first 100 members included) | annual only, per member | | Business | €11 per person per year | annual only, per seat |

What paying buys today: the space stops counting toward the account's three-space creation limit, it is never reclaimed as unused, and it carries a larger storage allowance (below).

Per-seat Business (decided 2026-07-22)

Business flipped from flat (€99/month / €999/year) to €11 per person per year β€” the price scales with the team instead of gating at a size the space has to grow into. The crossover with the old flat price was ~91 people, so a small business pays a fraction of what it used to and a big one continuously becomes the old plan. Mechanics, all held by the provisioner (per_seat in the price book; billing.go, meter.go):

  • Seats are counted server-side, never self-declared. A seat is a non-agent member (people in controld's stats) β€” bots are free. Checkout charges the live count as the Stripe line-item quantity; the ledger mirrors whatever the subscription actually bills (spaces.seats, from Stripe's own item via webhook).
  • Dropoffs and growth settle at renewal, never mid-cycle. In the week before each annual renewal the meter sweep re-counts and sets the subscription quantity with proration_behavior=none: shrinkage renews cheaper, growth renews dearer, and nobody sees a mid-year €33 refund or surprise top-up. That one Stripe knob is the entire dropoff policy.
  • Annual only. €11/12 β‰ˆ €0.92/person/month; Stripe's fixed €0.25 per charge makes tiny monthly invoices ~7%-fee territory and 12Γ— the dunning surface. Same reasoning as Family's annual-only, now applied where the per-charge ticket is small.
  • The allowance is per seat and pooled: 11 GB Γ— seats, one shared pot, so a heavy channel never hits an individual wall. Derivation per seat: net β‰ˆ €10.82, the 80/20 reserve takes €8.80, leaving ~€2.00 Γ· €0.168/GB-year β‰ˆ 12 GB β€” published as 11 (the elevens are load-bearing). At ~91 seats the pool crosses 1 TB exactly where revenue crosses the old €999 β€” the tables stay coherent.
  • Small teams run thinner, and that's accepted. Under ~10 seats the fixed per-space costs (resident slot, the stream replication rung) eat past the 20% line β€” a 3-person space runs maybe 50–60% margin, not 80%+. Storage is still capped per seat, so no team size is structurally loss-making; tiny businesses grow.

Storage allowances (as of 2026-07-14 β€” margin-derived)

Space creation is also gated by an account quota (3 free spaces; paid spaces don't count) and, when the home server enables it, a hashcash proof-of-work per creation β€” the anti-Sybil cost that runs inside the create animation.

Allowances are a function of margin (Paul's 80/20 rule, 2026-07-14): an allowance is the storage a space could fill forever with the tier still keeping β‰₯80% of gross as profit β€”

allowance_GB = (net βˆ’ 0.80 Γ— gross βˆ’ compute_cost) Γ· (storage_rate Γ— 12)

β€” computed at the tighter billing case. Two honest exceptions: the Free tier has no revenue (its 1 GB is pure cost containment), and Family at €5.50/year buys only ~3 GB at strict 80/20 β€” we hold it at 5 GB and accept a ~74% worst-case floor rather than shrink the family tier.

| Tier | Allowance | |---|---| | Free | 1 GB | | Family | 5 GB | | Community & Friends | 20 GB | | Business | 11 GB per person (pooled) |

The allowances ARE the enforced caps (LCHAT_CLOUD_STORAGE_CAPS β€” per-seat entries use the /seat suffix, e.g. business=11GB/seat) β€” the published table and the config must always match. A large team's pooled allowance deliberately exceeds the shared machine's ~38 GB disk: the promise is honored on demand β€” a Business space genuinely growing toward its allowance gets a Hetzner volume attached (minutes, up to 10 TB per volume) until attachment storage moves off-box to R2 (#550), which retires that ceremony entirely. Uploads past an allowance are refused (nothing is ever deleted, and messages always keep working).

Input rates (snapshot, 2026-07-11)

| Input | Rate | Source | |---|---|---| | Stripe fee (EU consumer card) | 1.5% + €0.25 per charge | Stripe pricing; EUR settlement, no FX | | Attachment storage (R2) | ~€0.014/GB-month | $0.015, zero egress | | DB snapshots (S3) | ~€0.021/GB-month | $0.023 | | Box (whole cloud plane) | ~€35/month | Hetzner + fixed services | | Resident-process slot | ~€0.81/month | box Γ· 40-instance capacity |

Hibernation is live in production (the activator, #550 Part 4: running on the box against the real S3 bucket, verified by a hibernating canary instance), and spaces adopt it per-host as the rollout proceeds (routes.hibernate). A flagged space that goes idle is an S3 prefix, not a process β€” marginal cost while asleep is storage alone, and the slot rate applies only to the fraction of time it's awake. The estimates below model a flagged space; a not-yet-flagged space still carries the full resident slot rate (~€9.70/year at full box density), which trims its margin by that amount until its flip. One deliberate permanent exception: a space with a bot sidecar never sleeps (the sidecar's WebSocket holds it awake) β€” one more reason AI usage carries its own meter instead of hiding in a flat price.

Durability per tier β€” the replication ladder (decided 2026-07-14)

The fleet's S3 bill is ~100% Tier-1 requests, not data (#836), and the one request stream that scales with activity is litestream's change-driven WAL sync β€” worth pennies a year on a quiet space and up to ~€145/year on a worst-case space that writes every second around the clock. That cost profile is why durability is now a per-plan replication class on the activator's replica (routes.replication; mechanism #866, billing push #869):

| Tier | Class | Awake sync cadence | Hard-crash loss window | Request cost/yr (est.) | |---|---|---|---|---| | Business | stream | change-driven ~1s | seconds | ~€2–20 typical; ~€145 worst case | | Community & Friends | batched | at most every 5m | minutes | ≀ ~€0.50 | | Free + Family | daily | at wake + every 24h | up to a day | pennies |

Three things the ladder deliberately does not change:

  • Every graceful path flushes in full β€” idle sleep, deploy, restart, shutdown all checkpoint the space to S3 regardless of class. The class only bounds what a sudden box loss can take, and only while awake.
  • Hibernation's parked copy is always exactly current β€” sleeping on a lower rung is not a weaker backup; the rung applies to awake windows only.
  • Nothing about confidentiality β€” the replica is the same ciphertext the server already holds.

The honest member-facing framing (held in the changelog and any plan copy): backed up every time your space goes quiet, and at least nightly; a catastrophic server failure may cost the most recent hours on Free/Family, minutes on Community, seconds on Business. One caveat priced in above: a space with a bot sidecar never sleeps, so for those the "at least nightly" floor is the real day-to-day cadence on the daily rung.

One Business plan, not a "Business Plus" (decided 2026-07-14). The full resilience stack β€” streaming replication, the retention ladder behind point-in-time restore, room to tighten the crash-failover window β€” costs €2–20/year on realistic Business spaces against revenue that scales with the team (per-seat since 2026-07-22: €330/year at 30 people; the decision was taken against the flat €999–1,188/year and holds at per-seat scale). A resilience delta that small can't carry a second paid tier: splitting it would add a Stripe price pair, picker copy, and a matrix cell to explain, to sell something we can afford to include. So Business simply includes best-available durability, and the ladder stays three legible rungs priced by what they actually cost. If a segment ever demands contractual RPO/RTO, multi-region replicas, or compliance-grade restore drills, that's a custom/Enterprise conversation β€” negotiated, not a checkbox tier β€” and the books will show its costs separately when it exists.

The model

For a tier with gross annual revenue G across n charges/year:

net      = G βˆ’ (0.25 Γ— n) βˆ’ (0.015 Γ— G)          # Stripe fees out
cost     = GB_stored Γ— storage_rate Γ— 12          # media, the only real dial
         + slot_rate Γ— 12 Γ— awake_fraction        # compute while awake
         + repl_requests                          # by replication class (see Durability):
                                                  #   daily/batched β‰ˆ €0; stream β‰ˆ €2–20
         + ~€0.10                                 # wakes, other requests, push (noise)
profit   = net βˆ’ cost
break_even_GB = net Γ· (storage_rate Γ— 12)         # where a space stops covering itself

Message text is never material: a decade of busy family chat is ~50 MB (~€0.01/year). The only way a space outspends its price is stored media.

Estimates per tier (snapshot, 2026-07-27)

Usage profiles are typical-case estimates, not caps. Business is per-seat, so it gets two team sizes β€” the structure holds at both:

| Tier | Gross/yr | Net/yr | Profile (est.) | Cost/yr (est.) | Profit/yr (est.) | Margin | Break-even storage | |---|---|---|---|---|---|---|---| | Family €5.50/y | €5.50 | €5.17 | 10 members, 5 GB, mostly asleep | ~€1.00 | ~€4.15 | ~76% | ~31 GB | | Community €11 min | €11.00 | €10.59 | 40 members (first 100 included), 11 GB, awake ~20% | ~€5.50 | ~€5.10 | ~46% | ~40 GB | | Community €0.11/member | €55.00 | €53.93 | 500 members, 11 GB, awake ~50% | ~€12.00 | ~€42 | ~76% | ~320 GB | | Business €11/p/y | €330.00 | €324.80 | 30 people, 60 GB pooled, awake ~50% | ~€20.00 | ~€305 | ~92% | ~1.9 TB | | Business €11/p/y | €1,650.00 | €1,625.00 | 150 people, 300 GB pooled, awake ~50% | ~€75.00 | ~€1,550 | ~94% | ~9.7 TB |

Readings:

  • Break-even storage is the number that matters. A Family space must hold ~31 GB of media forever before €5.50/year stops covering it. That makes #561's storage quotas easy to set generously: the shipped allowances (5 GB Family, 11 GB Community, 11 GB per seat Business) sit far below every tier's break-even, so no tier can structurally lose money while still feeling roomy in practice.
  • Stripe's fixed fee punishes small monthly charges. Family pays ~6% of gross in fees on its single annual charge; a hypothetical €0.46/month Family would pay ~11Γ—. This is why the whole ladder is annual only β€” at €0.11 a member, a monthly charge would be mostly Stripe fee (and a space is a years-scale commitment anyway).
  • The fixed floor is small. The whole plane costs ~€420/year; roughly 80 Family spaces, or ~40 Community minimums, or one 40-person Business space cover it outright. Beyond that, margin is contribution toward resilience and the co-operative endgame (#550 Part 10).
  • Business margin is deliberately not an infra story. At ~92–94% margin on realistic teams the price is buying priority support, SLAs, and features to come β€” not bytes. (Small teams run thinner β€” see Β§ Per-seat.) If that feels wrong when the books go public, that's the conversation the books exist to force.

What could invert these numbers

  1. AI/bot usage β€” excluded above by design; metered add-on or BYO key.
  2. Media hoarding past break-even β€” bounded by #561 quotas when they land.
  3. A space that never sleeps β€” bot-sidecar spaces; today that's a known subsidy, priced into the margins above.
  4. Rate changes β€” Stripe, R2/S3, or box pricing move; re-derive.

Re-deriving

Update the two snapshot tables (input rates + estimates) and the date stamps; the formulas don't change. This document publishes: the status site's Economics page (web/status/economics.{html,json}) is the public snapshot of these tables — update it in the same change and copy it to the box (docs/status.md § Keeping the tier-economics page current; the contract test pins the arithmetic). Two numbers stay out of the public copy by design: the per-box instance cap and the box disk size (the status site's capacity privacy rule — band words, never cap values). Current prices live in the provisioner's price book (LCHAT_STRIPE_PRICES on the cloud service; see cloud-provisioner.md § Billing); money truth lives in the Stripe dashboard; entitlement truth in the provisioner ledger. Related: #550 (architecture + public books), #561 (limits/meters), #562 (pricing decisions), #614 (member→admin subscriptions — a different product, same Stripe account).