toiljs 0.0.103 → 0.0.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,43 +1,66 @@
1
1
  # Understanding toil
2
2
 
3
- toil is one framework that gives you AAA-grade, hyper-scale infrastructure with zero configuration and no networking or distributed-systems knowledge required. You write a React frontend and a TypeScript backend in one project; toil runs both, plus a database, close to your users worldwide. Post-quantum login is one line. It just works out of the box.
3
+ toil is one framework for a whole web app: the frontend, the backend, and the database, in a single project, all running close to your users.
4
4
 
5
- Top-tier infrastructure is normally something a funded team assembles from ten rented vendors and babysits with deep expertise. toil makes the good version the default version, in a single framework, so a solo builder starts from the same baseline as that team. This section is the "why": what toil is, the problem it solves, how it works underneath, and why it is built the way it is. If you read nothing else first, read this. It is what turns "another framework" into "oh, that is the point."
5
+ You write React for the client and TypeScript for the server. toil compiles the server to WebAssembly and runs it at the edge, next to whoever is asking. Auth, database, email, realtime, and background jobs are already built in. Nothing to wire up, nothing to configure. A pizza site gets the same infrastructure a funded team would rent from ten separate vendors.
6
6
 
7
- ## The one big idea
7
+ This section explains what that means and why it holds up. Start here, then follow the links at the end.
8
8
 
9
- Almost every website has a split personality. The pretty part (pages, buttons) is served from machines all over the world, close to you. The important part (the database, where your data lives and changes) sits in **one place**, one region, often one machine. Post a comment in Tokyo when that database is in Virginia and your click flies halfway around the planet and back before anything happens.
9
+ ## What toil is
10
10
 
11
- toil is built to remove the split. Your **frontend** (React) and **backend** (TypeScript, compiled to a tiny WebAssembly program) both run at the **edge**, near your users. And **ToilDB** is built to distribute the writes too, so a write does not have to travel to one far-away box: every key has a home region that orders its writes, while the data replicates outward for fast local reads. One language, one project, one deploy, running close to everyone.
11
+ A toil project has three parts in one folder:
12
+
13
+ - `client/` is your React app: file-based routing, data loaders, and a typed client for calling the server.
14
+ - `server/` is your backend, plain TypeScript marked up with decorators like `@rest`, `@data`, and `@auth`. toil compiles it to a small sandboxed WebAssembly module.
15
+ - ToilDB is your database. It is already there. No connection string, no instance to spin up.
16
+
17
+ Types tie the three together. Change a field on the server and the client stops compiling until you fix it. Edge deployment, post-quantum login, and asset tamper-proofing are on by default, not features you bolt on later.
18
+
19
+ ## The problem it solves
20
+
21
+ A good web app should be fast everywhere, secure by default, and able to grow without a rewrite. Getting there is the hard part, and most of it has nothing to do with your actual product.
22
+
23
+ You assemble it from rented parts: a host, serverless functions, a database, an auth provider, email, a cache, a queue, analytics, a realtime service. Each is its own account, bill, and SDK, and you keep them all in sync. Under that sits a decade of legacy tooling and a node_modules folder heavier than your app. Worse, the fast and secure version is never the default. A CDN, careful caching, region tuning, hardened auth, current crypto: all of it is extra work, so most apps ship slower and less safe than they should.
24
+
25
+ toil deletes that assembly. One framework runs your frontend, backend, and database at the edge, next to users. Auth, email, realtime, and background jobs are built in and owned. Login is post-quantum out of the box. There is nothing to wire up and no infrastructure to reason about. The good version is the only version.
26
+
27
+ Distributing writes worldwide is one of the hard problems it handles under the hood. Most stacks spread reads everywhere but pin every write to one region, so a user far from it waits for a round trip and that region is a single point of failure. ToilDB is built to distribute the writes too: every key has a home region that orders its writes while the data copies outward for fast local reads. You never set any of it up.
12
28
 
13
29
  ```mermaid
14
30
  flowchart TB
15
- subgraph Ordinary["The ordinary web"]
16
- U1["User in Tokyo"] -->|fast| E1["Edge (pretty part)"]
17
- E1 -->|slow, one region| DB1[("Database in Virginia")]
31
+ subgraph Assemble["The usual way: rent and wire the parts yourself"]
32
+ direction TB
33
+ A["Your app"] --> H["host"]
34
+ A --> F["functions"]
35
+ A --> D["database"]
36
+ A --> Au["auth"]
37
+ A --> Em["email"]
38
+ A --> Rt["realtime"]
39
+ A --> J["jobs"]
18
40
  end
19
- subgraph Toil["toil"]
20
- U2["User in Tokyo"] -->|fast| E2["Edge near Tokyo<br/>frontend + backend + data"]
41
+ subgraph Toil["toil: one framework, at the edge, by default"]
42
+ direction TB
43
+ A2["Your app"] --> T["frontend + backend + database + auth +<br/>email + realtime + jobs, built in and near users"]
21
44
  end
22
45
  ```
23
46
 
24
- That is the entire pitch. Distributing reads is easy and everyone does it; distributing the **writes** is the hard part almost nobody does, and it is the reason most "global" apps are only half global. The rest of these pages is how toil pulls it off, and why it stays honest about what is live today versus what is built and deployment-gated.
47
+ ## Where to go from here
25
48
 
26
- ## Read these in order
49
+ Read these in order. Each one builds on the last.
27
50
 
28
- 1. **[Why toil? Who is it for?](./why-toil.md)** The problem with today's stacks, who benefits most, and the honest cases against.
29
- 2. **[The modern stack](./modern-stack.md)** The full catalog of modern tech baked in, owned by toil, with zero setup.
30
- 3. **[How toil works](./how-it-works.md)** The whole machine end to end: React client, WebAssembly backend, the edge node, and ToilDB.
31
- 4. **[What makes toil hyper-scalable](./hyperscale.md)** What "hyper-scale" means, and the mechanisms that let one tiny program serve the planet.
32
- 5. **[How toil is distributed](./distributed.md)** The hardest problem in web infrastructure, distributing the writes, and how ToilDB is built to solve it.
33
- 6. **[toil versus other frameworks](./vs-other-frameworks.md)** An honest comparison with Next.js, Rails, Django, serverless, edge runtimes, and backend-as-a-service.
34
- 7. **[Why toil is built this way (the RSG bar)](./design-principles.md)** The internal rubric, graded AAA down to D on its weakest axis, that toil holds itself against.
51
+ 1. **[Why toil, and who it is for](./why-toil.md)** What is wrong with a modern stack, who gains most from toil, and the honest cases against it.
52
+ 2. **[What comes built in](./modern-stack.md)** The full list of what toil owns and runs for you, and what it does not.
53
+ 3. **[How toil works](./how-it-works.md)** The whole path, from a React click through WebAssembly to ToilDB and back.
54
+ 4. **[Why it scales cheaply](./hyperscale.md)** How one small program can serve the whole planet without a per-app server bill.
55
+ 5. **[How toil distributes writes](./distributed.md)** One of the hardest problems in web infrastructure, and how ToilDB is built to solve it.
56
+ 6. **[toil next to other stacks](./vs-other-frameworks.md)** A fair comparison with Next.js, Rails, serverless, and the rest, wins and losses both.
57
+ 7. **[The bar toil holds itself to](./design-principles.md)** The RSG rubric, and its one rule: your grade is your weakest part.
35
58
 
36
- ## The short version
59
+ ## The short answer
37
60
 
38
- - **Who it is for:** people building real products who want global speed and reliability without a platform team or ten stitched-together vendors. See [Why toil](./why-toil.md).
39
- - **Why it is fast:** the code runs next to the user, with no slow trip to a central origin. See [Hyper-scale](./hyperscale.md).
40
- - **Why it is different:** it is built to distribute the writes, not just the reads. See [Distributed](./distributed.md).
41
- - **Why it is safe:** the backend is a sandbox, passwords never reach the server in a usable form (real post-quantum auth), secrets never ship in the code, and the browser verifies every asset it loads. See [Security](../concepts/security.md).
61
+ - **Who it is for:** anyone shipping a real product who wants global speed without a platform team or ten stitched-together services.
62
+ - **Why it is fast:** the code runs next to the user, with no trip to a distant origin.
63
+ - **Why it is different:** the whole stack is built in and owned, so there is nothing to assemble, and it distributes writes worldwide, not only reads.
64
+ - **Why it is safe:** the backend is sandboxed, passwords never reach the server in a usable form, secrets never ship in the code, and the browser checks every file it loads.
42
65
 
43
- One framework, zero config, AAA-grade from the first line. When you are ready to build, jump to [Getting started](../getting-started/README.md).
66
+ Ready to build? Jump to [Getting started](../getting-started/README.md).
@@ -1,58 +1,60 @@
1
- # Why toil is built this way (the RSG bar)
1
+ # Why toil is built this way
2
2
 
3
- toil is opinionated on purpose, and the purpose is a single one: reach top-tier ("AAA") infrastructure, and ship it as the **default**. AAA-grade tech is normally something you assemble from a dozen vendors and babysit with a team that understands distributed systems. toil makes the good version the version you get out of the box, in one framework, with zero configuration. A solo builder starts from the same baseline as a funded team.
3
+ toil is opinionated on purpose. The purpose is one thing: reach top-tier infrastructure and ship it as the **default**. AAA-grade tech is normally something you assemble from a dozen vendors and keep alive with a team that understands distributed systems. toil makes the good version the version you get out of the box. One framework, zero configuration. A solo builder starts from the same baseline as a funded team.
4
4
 
5
- Every decision on this page traces back to that one goal. This page is the rubric toil holds itself against, and the principles that rubric forces.
5
+ Every decision on this page traces back to that goal. Below is the rubric toil grades itself against, and the choices that rubric forces.
6
6
 
7
- ## The bar: one grade, set by the weakest link
7
+ ## How RSG grades an app
8
8
 
9
- **RSG** (Resilience and Scale Grade) is toil's internal rubric for how resilient, distributed, fast, lean, and secure an app actually is, scored as a single letter from **AAA** down to **D**. It grades nine axes, and one rule runs the whole thing: **your grade is your weakest axis**, never the average and never the best. To earn AAA, all nine must be AAA at the same time.
9
+ RSG stands for Resilience and Scale Grade. It is toil's internal rubric for how resilient and scalable an app really is, scored as a single letter from **AAA** down to **D**. It grades nine axes. One rule runs the whole thing: **your grade is your weakest axis**. Never the average, never the best. To earn AAA, all nine axes must be AAA at once.
10
10
 
11
11
  A globally edged frontend on a single-region database is capped by the database. A worldwide system running slow code is capped by latency. The lowest column sets the grade, every time.
12
12
 
13
- That rule exists to kill the most common lie in this space: calling a system "global scale" because the read path is global, while the write path is one box in one region. Averaging lets the strong axis hide the weak one. The minimum refuses to. RSG is not an external certification and no auditor issues it; it is a mirror the team holds up to find the weakest link and fix it first. The full rubric lives at the repository root in [`RSG.md`](../../RSG.md).
13
+ That rule kills the most common lie in this space: calling a system "global scale" because the read path is global, while the write path is one box in one region. Averaging lets the strong axis hide the weak one. The minimum refuses to.
14
14
 
15
- ## The principles the bar forces
15
+ RSG is not an external certification, and no auditor issues it. It is a mirror the team holds up to find the weakest link and fix it first. The full rubric lives at the repository root in [`RSG.md`](../../RSG.md).
16
16
 
17
- Aiming for AAA-as-default is not a slogan. It forces a specific handful of decisions, and they are the reason toil looks the way it does.
17
+ ## What the bar forces
18
18
 
19
- ### 1. The good, safe, fast version is the default, not an upgrade
19
+ Aiming for AAA as the default is not a slogan. It forces a specific set of decisions, and they are why toil looks the way it does.
20
20
 
21
- On most stacks the resilient path is a paid tier and the secure path is a checklist you get to later. toil inverts that: the strong version is what you get **before** you configure anything.
21
+ ### The strong version is the default
22
22
 
23
- - **Post-quantum login in about one line.** Enable auth and a password is stretched through an OPRF (ristretto255) and Argon2id into a deterministic ML-DSA-44 keypair. Only the public key ever leaves the device, and login runs ML-KEM-768 mutual auth so the client verifies the server too. The password never reaches the server in a usable form. ML-DSA and ML-KEM are the NIST-standardized algorithms meant to survive a quantum computer. You do not assemble any of that; you switch it on.
24
- - **Tamper-proofing is on, not opt-in.** Every shipped asset carries SHA-384 Subresource Integrity plus importmap integrity, so a modified script is rejected by the browser instead of run. Nothing to remember to turn on.
23
+ On most stacks the resilient path is a paid tier and the secure path is a checklist for later. toil flips that. The strong version is what you get before you configure anything.
25
24
 
26
- ### 2. Batteries are included, and owned
25
+ - **Post-quantum login in about one line.** Enable auth and a password is stretched through an OPRF (ristretto255) and Argon2id into a deterministic ML-DSA-44 keypair. Only the public key ever leaves the device. Login runs ML-KEM-768 mutual auth, so the client verifies the server too. The password never reaches the server in a usable form. ML-DSA and ML-KEM are the NIST-standardized algorithms built to survive a quantum computer. You do not assemble any of it. You switch it on.
26
+ - **Asset tamper-proofing is on by default.** Every shipped asset carries SHA-384 Subresource Integrity plus importmap integrity. A modified script is rejected by the browser instead of run. There is nothing to remember to turn on.
27
27
 
28
- Auth, [ToilDB](../database/README.md), email, rate limiting, analytics, realtime streaming, background jobs, materialized views, scheduled jobs, sessions and cookies, an environment and secrets store: all built and owned by toil, all first-party. That is not just convenience. It is the Dependencies axis, where zero third-party code on the critical path is what earns AAA. Nothing you cannot inspect or fix sits between a request and its response.
28
+ ### Everything is built in and first-party
29
29
 
30
- ### 3. One framework, not ten vendors
30
+ Auth, [ToilDB](../database/README.md), email, rate limiting, analytics, realtime streaming, background jobs, materialized views, scheduled jobs, sessions and cookies, an environment and secrets store. toil builds and owns all of it. This is the Dependencies axis, where zero third-party code on the critical path is what earns AAA. Nothing you cannot inspect or fix sits between a request and its response.
31
31
 
32
- You write a React frontend and a TypeScript backend in **one** project. toil runs both, plus the database, near your users worldwide. The browser calls the backend through a generated, fully typed `Server` client, so there is no hand-written fetch and no drift between the two halves. One project, one deploy, one mental model, instead of a frontend host plus an API host plus a database vendor plus an auth vendor plus a queue, each glued to the next.
32
+ ### One framework instead of ten vendors
33
33
 
34
- ### 4. Modern foundations, not legacy tooling
34
+ You write a React frontend and a TypeScript backend in one project. toil runs both, plus the database, near your users worldwide. The browser calls the backend through a generated, fully typed `Server` client. There is no hand-written fetch and no drift between the two halves. One project, one deploy, one mental model. The alternative is a frontend host plus an API host plus a database vendor plus an auth vendor plus a queue, each glued to the next.
35
35
 
36
- toil bets on current technology rather than propping up old tooling.
36
+ ### Modern foundations
37
37
 
38
- - **WebAssembly backends.** Your TypeScript compiles to a small, sandboxed WASM module. Because the sandbox is real, one edge box safely runs **many** tenants at once, and that multi-tenancy is exactly what makes running near everyone affordable.
39
- - **Post-quantum crypto** as the login default (see principle 1), not classical crypto you swap out later.
40
- - **End-to-end types** from the generated `Server` client, so a backend change that breaks the frontend is a compile error, not a production 500.
38
+ toil bets on current technology instead of propping up old tooling.
39
+
40
+ - **WebAssembly backends.** Your TypeScript compiles to a small, sandboxed WASM module. Because the sandbox is real, one edge box safely runs many tenants at once. That multi-tenancy is what makes running near everyone affordable.
41
+ - **Post-quantum crypto** as the login default, not classical crypto you swap out later.
42
+ - **End-to-end types** from the generated `Server` client. A backend change that breaks the frontend is a compile error, not a production 500.
41
43
  - **QUIC and WebTransport** carry realtime ([@stream](../concepts/tiers.md)).
42
44
 
43
- ### 5. Honesty about the limits
45
+ ### Honest limits
44
46
 
45
- toil grades itself on honesty, so the docs and the product both state limits plainly rather than overclaim.
47
+ toil grades itself on honesty, so the docs state the limits plainly.
46
48
 
47
- - **Distributed writes** are real in design and tested in the core: every key has one home region that orders its writes while data replicates outward for fast local reads (see [How toil is distributed](./distributed.md)). But live multi-region deployment is configuration-gated, not on by default, and the local dev database is a single in-process store. toil is **built** to distribute writes worldwide, and the mechanism is real; it is not the claim that every app is already running a live global write cluster today.
48
- - **Compute tiers:** the per-request edge (L1) is live and real. Regional, continental, and global-daemon tiers are opt-in and deployment-gated, not always-on for every app.
49
- - **Analytics** is real on the edge; the dev server returns sample data.
50
- - **Auth secrets** ship as clearly-insecure dev placeholders so `toiljs dev` just works. A real deployment must set its own.
51
- - toil is younger than the incumbents and its integration catalog is smaller. [vs other frameworks](./vs-other-frameworks.md) covers when not to reach for it.
49
+ - **Distributed writes** are real in design and tested in the core. Every key has one home region that orders its writes, while data replicates outward for fast local reads (see [How toil is distributed](./distributed.md)). But live multi-region deployment is configuration-gated, not on by default, and the local dev database is a single in-process store. toil is built to distribute writes worldwide, and the mechanism is real. The claim is not that every app is already running a live global write cluster today.
50
+ - **Compute tiers.** The per-request edge (L1) is live and real. Regional, continental, and global-daemon tiers are opt-in and deployment-gated, not always-on for every app.
51
+ - **Analytics** is real on the edge. The dev server returns sample data.
52
+ - **Auth secrets** ship as clearly insecure dev placeholders so `toiljs dev` just works. A real deployment must set its own.
53
+ - toil is younger than the incumbents, and its integration catalog is smaller. [vs other frameworks](./vs-other-frameworks.md) covers when not to reach for it.
52
54
 
53
- ## The bar in nine axes
55
+ ## The nine axes
54
56
 
55
- Each axis names a way a system can be weak. Each row is the single design decision toil makes so that axis cannot be the thing that caps it.
57
+ Each axis names a way a system can be weak. Each row is the single design choice toil makes so that axis cannot be the thing that caps it.
56
58
 
57
59
  | RSG axis | What it grades | The toil design choice that hits it |
58
60
  | --- | --- | --- |
@@ -66,9 +68,9 @@ Each axis names a way a system can be weak. Each row is the single design decisi
66
68
  | **Client performance + reach** | How well the shipped app runs on old and low-end devices as data grows | A lean React client: a small bundle and linear-or-better hot paths, so it stays smooth on weak hardware, not just new flagships. |
67
69
  | **Modern stack + compatibility** | Current foundations, *with* graceful fallback for older clients | WebAssembly backends, post-quantum auth, and QUIC/WebTransport realtime, negotiating down cleanly so a client one version behind still works. |
68
70
 
69
- ## The punchline
71
+ ## Why every axis has to hold
70
72
 
71
- toil is opinionated because being AAA on **every** axis at once forces these choices, and it delivers them as the default so you do not have to earn each one by hand. You cannot reach the top grade with a fast frontend on a centralized database, or a global system running slow code, or a modern stack that only works on the newest browser. The weakest-link rule closes every one of those escape hatches. Any framework that lets a single axis slip is, by its own honest scoring, not AAA. Holding all nine at once, out of the box, is the whole reason toil looks the way it does.
73
+ toil is opinionated because being AAA on every axis at once forces these choices. It delivers them as the default, so you do not have to earn each one by hand. You cannot reach the top grade with a fast frontend on a centralized database. You cannot reach it with a global system running slow code, or a modern stack that only works on the newest browser. The weakest-link rule closes every one of those escape hatches. Any framework that lets a single axis slip is, by its own honest scoring, not AAA. Holding all nine at once, out of the box, is why toil looks the way it does.
72
74
 
73
75
  ## Related
74
76
 
@@ -1,34 +1,34 @@
1
1
  # How toil is distributed
2
2
 
3
- Distributing a website's reads is easy. Distributing its writes is the hard part almost nobody solves, and it is why "global" apps are usually only half global. Here is the problem, and how ToilDB (the database built into toil) is built to distribute the writes.
3
+ Spreading a website's reads across the world is easy. Spreading its writes is hard, and almost nobody solves it. That is why most "global" apps are only global for reading. This page covers the problem and how ToilDB, the database built into toil, is built to distribute the writes.
4
4
 
5
- ## Reads are easy, writes are hard
5
+ ## Why writes are the hard part
6
6
 
7
- A read never changes anything, so you copy your data to servers worldwide and let each user read the nearest copy. Every copy agrees: a reader in Tokyo and one in Paris both get a fast, local answer.
7
+ A read changes nothing, so you copy your data to servers worldwide and let each user read the nearest copy. Every copy agrees. A reader in Tokyo and one in Paris both get a fast, local answer.
8
8
 
9
- A write is a change, and two writes to the *same thing* can collide. A counter says `10`. Tokyo and Paris both read `10`, both add one, both write `11`. The real answer was `12`, so one add vanished with no error. That is a **write conflict**.
9
+ A write is a change, and two writes to the same key can collide. A counter says `10`. Tokyo and Paris both read `10`, both add one, both write `11`. The real answer was `12`. One add vanished, with no error. That is a **write conflict**.
10
10
 
11
- You could make every copy agree before accepting a write, but the network will eventually split (a **partition**), and the **CAP tradeoff** says that during a split you keep only two of consistency, availability, and partition tolerance. You either refuse the write (correct but unavailable) or accept it on one side and reconcile later (available but briefly inconsistent). Distributing writes is a real tradeoff to design around, not a bug to patch away.
11
+ You could make every copy agree before accepting a write. The network, though, will eventually split into a **partition**. During a split the **CAP tradeoff** says you keep only two of three: consistency, availability, and partition tolerance. You either refuse the write, which is correct but unavailable, or accept it on one side and reconcile later, which is available but briefly inconsistent. Distributing writes is a tradeoff to design around. There is no patch that removes it.
12
12
 
13
- ## So almost everyone centralizes the write database
13
+ ## The usual fix: one write database
14
14
 
15
- Faced with that, nearly every stack keeps **one** primary write database in **one** region and spreads only read replicas worldwide. All writes funnel to that one box, one at a time, so conflicts cannot happen.
15
+ So nearly every stack keeps **one** primary write database in **one** region and spreads only read replicas worldwide. Every write funnels to that one box, one at a time, so conflicts cannot happen.
16
16
 
17
- It is a reasonable choice, and it hides two costs the [RSG rubric](./design-principles.md) flags on its data-path axis:
17
+ It is a reasonable choice. It also hides two costs the [RSG rubric](./design-principles.md) flags on its data-path axis:
18
18
 
19
- - **Far writes are slow.** Post from Tokyo to a primary in Virginia and your write crosses the planet and back before anything saves. The page was local; the action was not.
20
- - **The primary is a single point of failure.** One region holds every write, so if it has a bad day, nothing anywhere can be changed.
19
+ - **Far writes are slow.** Post from Tokyo to a primary in Virginia, and the write crosses the planet and back before anything saves. The page loaded locally. The write did not.
20
+ - **The primary is a single point of failure.** One region holds every write. If it has a bad day, nothing anywhere can change.
21
21
 
22
- The read path is global; the write path is one machine in one city. Under RSG's weakest-link rule, that single data path caps the whole system.
22
+ The read path is global. The write path is one machine in one city. Under RSG's weakest-link rule, that single data path caps the whole system.
23
23
 
24
- ## ToilDB's answer: every key has a home
24
+ ## ToilDB's model: one home per key
25
25
 
26
- ToilDB gives **every key its own home**. A key is the label you store data under (a user id, a username, a room name; see the [database overview](../database/README.md)). Each key is assigned one home: the single source of truth that orders its writes.
26
+ ToilDB gives **every key its own home**. A key is the label you store data under: a user id, a username, a room name. See the [database overview](../database/README.md). Each key gets one home: the single source of truth that orders its writes.
27
27
 
28
- Two things follow, and together they are the whole trick:
28
+ Two things follow from that:
29
29
 
30
- - **Writes to one key are safe.** Every write to a key travels to that key's home, which **serializes** them (applies them one at a time, in order). Both counter adds are ordered at the counter's home, so the result is `12`. No global lock over the whole database.
31
- - **Writes spread worldwide.** Different keys get different homes, so total write load spreads out. Tokyo users' data can home near Tokyo, Paris users' near Paris. No single box every write funnels through, so no single bottleneck.
30
+ - **Writes to one key are safe.** Every write to a key travels to that key's home, which **serializes** them: it applies them one at a time, in order. Both counter adds are ordered at the counter's home, so the result is `12`. No global lock over the whole database.
31
+ - **Writes spread worldwide.** Different keys get different homes, so total write load spreads out. Tokyo users' data can home near Tokyo, Paris users' near Paris. No single box carries every write, so no single bottleneck.
32
32
 
33
33
  ```mermaid
34
34
  flowchart TB
@@ -39,13 +39,13 @@ flowchart TB
39
39
  KA -.-> KC
40
40
  ```
41
41
 
42
- Reads stay local: each key still replicates out, so a reader anywhere gets a nearby copy. Those copies are **eventually consistent**, meaning that for a brief moment (usually milliseconds) after a write lands at the home, a far read can lag before it catches up. For almost all app data this is invisible; the [database overview](../database/README.md) has the full picture.
42
+ Reads stay local. Each key still replicates outward, so a reader anywhere gets a nearby copy. Those copies are **eventually consistent**. For a brief moment after a write lands at the home, a far read can lag before it catches up. That moment is usually a few milliseconds, and for almost all app data it is invisible. The [database overview](../database/README.md) has the full picture.
43
43
 
44
- Which location owns a key is decided by a shared formula (rendezvous hashing) every node computes the same way, so any node routes a write to the right home with no central coordinator. A key's home can move to follow demand, without rehashing the database.
44
+ A shared formula decides which location owns a key. It is called rendezvous hashing, and every node computes it the same way, so any node routes a write to the right home with no central coordinator. A key's home can move to follow demand, without rehashing the database.
45
45
 
46
- ## The seven families pick the right consistency tool
46
+ ## The seven families
47
47
 
48
- One "home orders the writes" rule fixes the counter, but different jobs want different guarantees. So ToilDB ships **seven families**, each a collection type tuned for one shape of data, each exposing only the operations that are safe and fast for it:
48
+ One "home orders the writes" rule fixes the counter. Different jobs, though, want different guarantees. So ToilDB ships **seven families**. Each is a collection type tuned for one shape of data, and each exposes only the operations that are safe and fast for it.
49
49
 
50
50
  | Family | What it gives |
51
51
  | --- | --- |
@@ -57,23 +57,31 @@ One "home orders the writes" rule fixes the counter, but different jobs want dif
57
57
  | [Membership](../database/membership.md) | Sets of who belongs to what |
58
58
  | [View](../database/views.md) | A read-optimized result a background job builds |
59
59
 
60
- Distributing writes is not one problem with one answer; each family is the right tool for one shape.
60
+ Distributing writes has no single answer. Each family is the right tool for one shape of data.
61
61
 
62
- ## The hard machinery toil provides so you do not have to
62
+ ## The machinery underneath
63
63
 
64
- The per-key-home model only works if a lot of unglamorous machinery runs reliably across a flaky network, and ToilDB owns it: per-key **placement** and safe **rehoming** (a rising epoch plus a fencing token so the old owner stops the instant the new one takes over), ordered **cross-region replication** with per-stream cursors that detect and backfill gaps, **idempotent apply** so redelivered writes cannot double-count, **capacity escrow** and **tenant quotas**, and **failover** with snapshot re-seeding for a cell that has fallen too far behind. Getting all of these right at once is exactly why truly distributed websites are rare.
64
+ The per-key-home model only works if a lot of unglamorous machinery runs reliably across a flaky network. ToilDB owns all of it:
65
65
 
66
- ## What is real today, honestly
66
+ - Per-key **placement** and safe **rehoming**: a rising epoch plus a fencing token, so the old owner stops the instant the new one takes over.
67
+ - Ordered **cross-region replication** with per-stream cursors that detect and backfill gaps.
68
+ - **Idempotent apply**, so a redelivered write cannot double-count.
69
+ - **Capacity escrow** and **tenant quotas**.
70
+ - **Failover** with snapshot re-seeding for a cell that has fallen too far behind.
67
71
 
68
- This is the hard part almost nobody does, so here is a straight account of where it stands.
72
+ Getting all of these right at once is why truly distributed websites are rare.
69
73
 
70
- The per-key-home model and all of its core logic (placement, rehoming, replication, idempotent apply, escrow, quotas, failover) are **built and tested**. The mechanism is real, not a diagram.
74
+ ## What is real today
71
75
 
72
- What is not on by default is the **live multi-region deployment**: wiring many real regions into one running mesh (WAN routing) and the [ScyllaDB](https://www.scylladb.com/) storage that backs a production cluster are **configuration-gated**, so you switch them on for a real deployment rather than getting a live global write cluster automatically. The full database-level **leader fencing** on the write path is also still landing (a host-side leader gate is the current version). The design is settled; the last-mile host wiring is what remains.
76
+ This is the hard part that almost nobody ships, so here is a straight account of where it stands.
73
77
 
74
- On your laptop, `toiljs dev` runs a single **in-process** database: everything homes in one place, so your code behaves exactly as it will worldwide, but the distribution only spreads out once you deploy with the multi-cell backing configured. You write your app the same way either way; that is the point.
78
+ The per-key-home model and all its core logic are **built and tested**: placement, rehoming, replication, idempotent apply, escrow, quotas, failover. This is running code, and it passes its tests.
75
79
 
76
- The honest one-liner: toil is **built** to distribute writes worldwide, the mechanism is real, and turning it on across live regions is a deployment step, not a rewrite of your app.
80
+ The **live multi-region deployment** is not on by default. Wiring many real regions into one running mesh (the WAN routing) and the [ScyllaDB](https://www.scylladb.com/) storage that backs a production cluster are **configuration-gated**. You switch them on for a real deployment. You do not get a live global write cluster automatically. The full database-level **leader fencing** on the write path is also still landing, and a host-side leader gate is the current version. The design is settled. What remains is the last-mile host wiring.
81
+
82
+ On your laptop, `toiljs dev` runs a single **in-process** database. Everything homes in one place, so your code behaves exactly as it will worldwide. The distribution only spreads out once you deploy with the multi-cell backing configured. You write your app the same way either way.
83
+
84
+ toil is **built** to distribute writes worldwide. The mechanism runs today. Turning it on across live regions is a deployment step, not a rewrite of your app.
77
85
 
78
86
  ## Related
79
87
 
@@ -1,23 +1,23 @@
1
1
  # How toil works
2
2
 
3
- The whole machine, end to end: what you write, what the build produces, and what happens when a user makes a request. Every term is defined as it appears. You configure none of the moving parts below; this page just explains them.
3
+ This page walks one app from source to response. What you write, what the build produces, and what happens when a request arrives. Every term is defined where it first appears. You configure none of the machinery below. This page just explains it.
4
4
 
5
- ## One project, two homes
5
+ ## The client and the server
6
6
 
7
- You build a toil app as a single project, and your code lives in two places.
7
+ A toil app is one project. Your code lives in two folders.
8
8
 
9
- - **`client/`** is a **React** frontend (with Vite): file-based routing, data loaders, the usual components. It runs in the user's browser.
10
- - **`server/`** is your backend, written in **TypeScript with decorators**. You mark a class `@rest` to expose HTTP endpoints, `@service` for typed RPC, `@stream` for realtime, `@daemon` for background jobs, `@database`/`@collection` for stored data, and `@auth`/`@user` for login. There are no servers to provision and no routes to wire by hand: the decorator is the wiring.
9
+ - **`client/`** is a **React** frontend built with Vite. File-based routing, data loaders, the usual components. It runs in the user's browser.
10
+ - **`server/`** is your backend, written in **TypeScript with decorators**. Mark a class `@rest` for HTTP endpoints, `@service` for typed RPC, `@stream` for realtime, `@daemon` for background jobs, `@database` or `@collection` for stored data, `@auth` or `@user` for login. There are no servers to provision and no routes to wire by hand. The decorator is the wiring.
11
11
 
12
12
  That is the whole surface. One repo, one language family, one `toiljs dev`.
13
13
 
14
14
  ## What the build produces
15
15
 
16
- `toiljs build` turns that one project into three kinds of output, because the browser and the edge need different things.
16
+ `toiljs build` turns that one project into three kinds of output. The browser and the edge need different things.
17
17
 
18
- **1. The client bundle.** Your React app plus any pages toil renders ahead of time, packaged as ordinary web files (HTML, JS, CSS, images) that run in the browser. Every shipped asset is fingerprinted with SHA-384 Subresource Integrity, so a browser refuses a file that was tampered with in transit.
18
+ **The client bundle.** Your React app, plus any pages toil renders ahead of time. It ships as ordinary web files that run in the browser: HTML, JS, CSS, images. Every asset is fingerprinted with SHA-384 Subresource Integrity, so the browser refuses a file that was tampered with in transit.
19
19
 
20
- **2. The server WASM.** Your `server/` backend, compiled by the **toilscript** compiler into a small, sandboxed **WebAssembly** module. It runs on the edge, not in the browser and not in Node. The build emits three artifacts, one per compute tier:
20
+ **The server WASM.** Your `server/` backend, compiled by the **toilscript** compiler into a small sandboxed **WebAssembly** module. It runs on the edge, not in the browser and not in Node. The build emits three artifacts, one per compute tier.
21
21
 
22
22
  | Artifact | Holds | Runs |
23
23
  | --- | --- | --- |
@@ -25,22 +25,22 @@ That is the whole surface. One repo, one language family, one `toiljs dev`.
25
25
  | `release-stream.wasm` | realtime handlers (`@stream`) | for the life of a connection |
26
26
  | `release-cold.wasm` | background and scheduled jobs (`@daemon`) | on a timer, worldwide-singleton |
27
27
 
28
- **3. The generated typed client (`shared/server.ts`).** toil reads the shape of your backend and generates a small browser-side client from it. Your React code calls a normal async function (`Server.REST.*`, `Server.Stream.*`, `Server.<service>`) and the types line up end to end: rename a field on the server and the frontend stops compiling until you fix it. No hand-written `fetch`, no drift.
28
+ **The generated typed client, `shared/server.ts`.** toil reads the shape of your backend and generates a small browser-side client from it. Your React code calls a normal async function, `Server.REST.*` or `Server.Stream.*` or `Server.<service>`, and the types line up end to end. Rename a field on the server and the frontend stops compiling until you fix it. No hand-written `fetch`, no drift.
29
29
 
30
- **WebAssembly, in two sentences:** a compact binary format that runs at close to native speed with no interpreter warm-up, inside a **sandbox**, a locked box that cannot open files, reach the operating system, or make network calls on its own. It touches the outside world only through the small, fixed set of functions the host hands it (read the request, build a response, query the database), which is exactly what makes it safe to pack many apps onto one shared machine. ([Why that matters for scale](./hyperscale.md).)
30
+ A word on **WebAssembly**. It is a compact binary format that runs at close to native speed with no interpreter warm-up. It runs inside a **sandbox**: a locked box that cannot open files, reach the operating system, or make network calls on its own. The guest touches the outside world only through a small fixed set of functions the host hands it. Read the request, build a response, query the database. That narrow surface is what makes it safe to pack many apps onto one shared machine. ([Why that matters for scale](./hyperscale.md).)
31
31
 
32
- toilscript is a strict TypeScript dialect (explicit value types, no `any`, no runtime `RegExp`); the [decorators reference](../concepts/decorators.md) covers the full set.
32
+ toilscript is a strict TypeScript dialect: explicit value types, no `any`, no runtime `RegExp`. The [decorators reference](../concepts/decorators.md) covers the full set.
33
33
 
34
- ## The edge node
34
+ ## The edge nodes
35
35
 
36
- Your WASM does not run on a laptop or in one central data center. It runs on the **edge**: a fleet of Rust runtime nodes spread across many cities, where each user is served by whichever node is physically closest. There is no **origin server**, no single far machine every request funnels back to, because your backend and its data are already at the edge.
36
+ Your WASM does not run on a laptop or in one central data center. It runs on the **edge**: a fleet of Rust runtime nodes spread across many cities. Each user is served by whichever node is physically closest. There is no **origin server**, no single far machine every request funnels back to. Your backend and its data are already at the edge.
37
37
 
38
38
  Two things make this work at the density it needs.
39
39
 
40
- - **Multi-tenant on shared boxes.** Because each app is a tiny sandboxed module, one edge box safely runs many apps at once. That shared density is what makes putting compute near everyone affordable instead of a luxury.
41
- - **A custom userspace datapath.** The node handles network packets itself in userspace (multi-queue, bypassing the operating system's network stack) to keep the per-request cost low as traffic grows. **QUIC** and **WebTransport** ride on top to power realtime `@stream` connections.
40
+ - **Multi-tenant on shared boxes.** Each app is a tiny sandboxed module, so one edge box safely runs many apps at once. That shared density is what makes putting compute near everyone affordable instead of a luxury.
41
+ - **A custom userspace datapath.** The node handles network packets itself in userspace, multi-queue, bypassing the operating system's network stack. This keeps the per-request cost low as traffic grows. **QUIC** and **WebTransport** ride on top to power realtime `@stream` connections.
42
42
 
43
- ## The request lifecycle
43
+ ## What happens on a request
44
44
 
45
45
  A request never leaves the neighborhood. It lands on the nearest edge node, and everything happens right there.
46
46
 
@@ -67,28 +67,28 @@ sequenceDiagram
67
67
  ```
68
68
 
69
69
  1. **The request lands on the closest edge node.** The network routes the user there automatically.
70
- 2. **Page or code?** If the path is a prerendered page, a server-rendered page, or a static asset, the edge serves it directly and never wakes your backend. This is the fast path for most page loads.
71
- 3. **Otherwise the host runs your guest.** The **WASM host** (trusted Rust) decodes the raw bytes into a `Request`, then calls into your **guest module** (your sandboxed WASM) at its single entry point, which routes to the handler you wrote.
72
- 4. **Your handler reads and writes locally.** When it needs stored data it talks to [ToilDB](../database/README.md), which has a copy right there at the edge. No ocean crossing.
73
- 5. **Your handler returns a `Response`,** the host encodes it back to bytes, and the edge sends it to the browser.
70
+ 2. **Page or dynamic call.** A prerendered page, a server-rendered page, or a static asset is served directly by the edge, which never wakes your backend. This is the fast path for most page loads.
71
+ 3. **Otherwise the host runs your guest.** The **WASM host**, trusted Rust, decodes the raw bytes into a `Request`. It calls into your **guest module**, your sandboxed WASM, at its single entry point, which routes to the handler you wrote.
72
+ 4. **Your handler reads and writes locally.** When it needs stored data it talks to [ToilDB](../database/README.md), which keeps a copy right there at the edge. No ocean crossing.
73
+ 5. **Your handler returns a `Response`.** The host encodes it back to bytes and the edge sends it to the browser.
74
74
 
75
- The mental model for your backend: a function of the request. Bytes in, bytes out, one request at a time.
75
+ The mental model for your backend is a function of the request. Bytes in, bytes out, one request at a time.
76
76
 
77
- ### Stateless by default
77
+ ### Why the backend is stateless
78
78
 
79
- A fresh copy of your handler serves each request, and the next request might be served by a node on the other side of the planet, so anything you set on an instance field does not survive. This is a feature: interchangeable copies with nothing to coordinate are what let the backend scale worldwide by simply adding more nodes. When you need something to persist, write it to ToilDB. (See the [backend overview](../backend/README.md#stateless-by-default).)
79
+ A fresh copy of your handler serves each request. The next request might land on a node on the other side of the planet, so anything you set on an instance field does not survive. This is deliberate. Interchangeable copies with nothing to coordinate are what let the backend scale worldwide by adding more nodes. When you need something to persist, write it to ToilDB. See the [backend overview](../backend/README.md#stateless-by-default).
80
80
 
81
- ## Where the data lives: ToilDB
81
+ ## The database, ToilDB
82
82
 
83
- State lives in [ToilDB](../database/README.md), toil's own database, replicated next to your code at the edge. It offers seven purpose-built families (Documents, Unique, Counter, Events, Membership, Capacity, View), so you pick the shape that fits instead of forcing everything into one table.
83
+ State lives in [ToilDB](../database/README.md), toil's own database, replicated next to your code at the edge. It offers seven purpose-built families: Documents, Unique, Counter, Events, Membership, Capacity, View. You pick the shape that fits instead of forcing everything into one table.
84
84
 
85
- Its hard trick is **distributed writes**. Every key has one **home region** that orders its writes, while the data replicates outward so reads stay fast and local everywhere. Most stacks distribute reads but keep writes pinned to one region; toil is built to distribute both.
85
+ The hard part is **distributed writes**. Every key has one **home region** that orders its writes, while the data replicates outward so reads stay fast and local everywhere. Most stacks distribute reads but pin writes to one region. toil is built to distribute both.
86
86
 
87
- Be honest about where this stands. The home-region model and its core logic are real and tested, but a *live* multi-region deployment (WAN routing, the ScyllaDB backing) is configuration-gated, not switched on for every app by default, and a far read can lag its home by a few milliseconds (eventual consistency). Your local `toiljs dev` database is a single in-process store. The write model and its trade-off are covered in [how toil is distributed](./distributed.md).
87
+ Where this stands today. The home-region model and its core logic are real and tested. A live multi-region deployment, meaning WAN routing over the ScyllaDB backing, is configuration-gated. It is not switched on for every app by default. A far read can also lag its home by a few milliseconds, the eventual-consistency trade-off. Your local `toiljs dev` database is a single in-process store. The [distributed writes page](./distributed.md) covers the write model and its trade-off in full.
88
88
 
89
- ## The compute tiers
89
+ ## The four compute tiers
90
90
 
91
- Not all backend code has the same lifespan. toil sorts it into four tiers, and the build assigns each piece automatically from its decorator.
91
+ Not all backend code has the same lifespan. toil sorts it into four tiers, and the build assigns each piece from its decorator automatically.
92
92
 
93
93
  | Tier | What runs here | Status |
94
94
  | --- | --- | --- |
@@ -96,9 +96,9 @@ Not all backend code has the same lifespan. toil sorts it into four tiers, and t
96
96
  | **L2 / L3** | longer-lived regional and continental work, `@stream` realtime | opt-in, deployment-gated |
97
97
  | **L4** | a single worldwide `@daemon` for background and scheduled jobs | opt-in, deployment-gated |
98
98
 
99
- Most apps live entirely on **L1**, and that tier is real and running today. L2 through L4 are built and opt-in, not always-on for every app. Full detail is on the [tiers page](../concepts/tiers.md).
99
+ Most apps live entirely on **L1**, which is real and running today. L2 through L4 are built and opt-in, not always-on for every app. Full detail is on the [tiers page](../concepts/tiers.md).
100
100
 
101
- ## The pieces
101
+ ## The parts of a running app
102
102
 
103
103
  Five parts make up a running toil app. You have now met all of them.
104
104
 
@@ -110,7 +110,7 @@ Five parts make up a running toil app. You have now met all of them.
110
110
  | **ToilDB** | the database with distributed writes, replicated next to your code | the edge |
111
111
  | **The four tiers** | where and for how long a piece of backend code lives | L1 nearest, up to L4 worldwide |
112
112
 
113
- None of these need configuring to get the good version. You write React and decorated TypeScript; the build, the edge, and the database are the default, not a stack you assemble and babysit.
113
+ None of these need configuring to get the good version. You write React and decorated TypeScript. The build, the edge, and the database come as the default, not a stack you assemble and babysit.
114
114
 
115
115
  ## Related
116
116
 
@@ -1,28 +1,28 @@
1
1
  # What makes toil hyper-scalable
2
2
 
3
- **Hyper-scale** is serving very large, worldwide traffic at low latency without rebuilding your app as it grows. The test: when traffic goes from a thousand users to a hundred million across every continent, do you rewrite the system, or just run more of it?
3
+ Hyper-scale means serving very large worldwide traffic at low latency without rebuilding your app as it grows. Picture traffic climbing from a thousand users to a hundred million across every continent. Do you rewrite the system, or just run more of it?
4
4
 
5
- Plenty of stacks can reach that scale if you throw money at it: dedicated infrastructure per app, a rented vendor for each moving part, and an ops team to keep the seams from tearing. toil was built for the same scale from the other direction: **cheaply and efficiently**. The whole design is aimed at making top-tier reach the default, not a budget line. Cost is the point of this page.
5
+ Any stack can reach that scale if you spend enough: dedicated infrastructure per app, a rented vendor for each moving part, and an ops team to keep the seams from tearing. toil reaches the same scale from the other direction, cheaply. The whole design aims to make worldwide reach a default, not a budget line. This page is about cost.
6
6
 
7
- ## Why hyper-scale is normally expensive
7
+ ## Why serving the whole world is normally expensive
8
8
 
9
- Running near your users usually means paying for it in three places at once:
9
+ Running near your users usually means paying in three places at once.
10
10
 
11
- - **Dedicated infrastructure per app.** Each app gets its own boxes, its own containers, its own always-warm capacity. Spread that across many cities and you are renting a lot of mostly-idle hardware.
12
- - **A far-away origin.** Most stacks serve pages from everywhere but send anything real back to one origin server in one region. Every write and every dynamic call pays for a round trip across the planet.
13
- - **A centralized write database.** The reads scale out; the writes funnel into one primary in one city. That box is both the bottleneck and the thing you overprovision to keep ahead of.
11
+ - **Dedicated infrastructure per app.** Each app gets its own boxes, its own containers, its own always-warm capacity. Spread that across many cities and you rent a lot of mostly-idle hardware.
12
+ - **A far-away origin.** Most stacks serve pages from everywhere but send anything real back to one origin in one region. Every write and every dynamic call pays for a round trip across the planet.
13
+ - **A centralized write database.** Reads scale out. Writes funnel into one primary in one city. That box is both the bottleneck and the thing you overprovision to stay ahead of.
14
14
 
15
- Each of those is a cost multiplier, and they stack. toil removes all three.
15
+ These are cost multipliers, and they stack. toil removes all three.
16
16
 
17
- ## How toil makes it cheap
17
+ ## The three things that make toil cheap
18
18
 
19
19
  Three mechanisms do the work, and they reinforce each other.
20
20
 
21
- **1. Density: one box safely runs many apps.** Your backend compiles to its own tiny, [sandboxed](./how-it-works.md#what-build-produces) WebAssembly module that starts fast, runs at near-native speed, and cannot touch another tenant's files, memory, or network. Because the sandbox is that tight, **one shared edge box holds many apps at once** instead of one app per machine. That multi-tenant density is what makes running near everyone affordable: you are not renting dedicated hardware in fifty cities, you are one tenant on boxes that are already there and already busy.
21
+ **1. Density: one box safely runs many apps.** Your backend compiles to its own tiny [sandboxed](./how-it-works.md#what-build-produces) WebAssembly module. It starts fast, runs at near-native speed, and cannot touch another tenant's files, memory, or network. Because the sandbox is that tight, one shared edge box holds many apps at once instead of one app per machine. That density is what makes running near everyone affordable. You are not renting dedicated hardware in fifty cities. You are one tenant on boxes that are already there and already busy.
22
22
 
23
- **2. Edge locality: no trip to a central origin.** toil has no origin server. Every request runs on the [edge](../concepts/tiers.md) node nearest the user, on the per-request **L1 hot path**: the network hands the bytes to the WASM host, your handler runs, a response goes back, all in one place. There is no slow hop to a faraway box to make the request "real." Removing the origin removes both the latency and the standing cost of running one.
23
+ **2. Edge locality: no trip to a central origin.** toil has no origin server. Every request runs on the [edge](../concepts/tiers.md) node nearest the user, on the per-request L1 hot path. The network hands the bytes to the WASM host, your handler runs, and the response goes back, all in one place. There is no slow hop to a faraway box to make the request real. Removing the origin removes both the latency and the standing cost of running one.
24
24
 
25
- **3. Local reads, homed writes.** The data your handlers share lives in [ToilDB](../database/README.md), replicated outward so every edge node reads from a copy right next to it. Writes are not centralized either: every key has one **home region** that orders its writes, while the data replicates out for fast local reads. So you get nearby reads everywhere without a single primary that every write funnels through, and without paying to overprovision one. The mechanism and its honest trade-off (eventual consistency) are in [how toil is distributed](./distributed.md).
25
+ **3. Local reads, homed writes.** The data your handlers share lives in [ToilDB](../database/README.md), replicated outward so every edge node reads from a copy right next to it. Writes are not centralized. Every key has one home region that orders its writes, and the data replicates out for fast local reads. You get nearby reads everywhere without a single primary that every write funnels through, and without paying to overprovision one. The [distributed writes](./distributed.md) page covers the mechanism and its honest trade-off, eventual consistency.
26
26
 
27
27
  ```mermaid
28
28
  flowchart LR
@@ -42,24 +42,24 @@ flowchart LR
42
42
  end
43
43
  ```
44
44
 
45
- The left side has one hot center every user drags a request to and back from, plus its dedicated fleet, a cost no amount of caching removes. The right side has no center and no per-app fleet: add a city, add a shared box, and every tenant on it gets that city for near nothing.
45
+ The left side has one hot center every user drags a request to and back from, plus its dedicated fleet. No amount of caching removes that cost. The right side has no center and no per-app fleet. Add a city, add a shared box, and every tenant on it gets that city for near nothing.
46
46
 
47
- ## Why this is cheap, in one line each
47
+ ## Why each mechanism lowers the cost
48
48
 
49
- - **Density** means the cost of an edge presence is split across many tenants, not carried by one app.
50
- - **Edge locality** means no origin fleet to run and no cross-planet round trip to pay for on every real request.
51
- - **No dedicated infra** means you scale by adding interchangeable shared nodes, not by standing up a new stack per app.
49
+ - **Density** splits the cost of an edge presence across many tenants instead of loading it on one app.
50
+ - **Edge locality** means no origin fleet to run and no cross-planet round trip on every real request.
51
+ - **No dedicated infrastructure** means you scale by adding interchangeable shared nodes, not by standing up a new stack per app.
52
52
 
53
- Take any one away and a cost reappears: no density and running near everyone is a luxury again; no edge locality and you are back to paying for an origin; a centralized write path and the database caps you and gets overprovisioned to compensate.
53
+ Take any one away and a cost comes back. Without density, running near everyone is a luxury again. Without edge locality, you pay for an origin. With a centralized write path, the database caps you and gets overprovisioned to compensate.
54
54
 
55
- ## An honest note
55
+ ## What is real today
56
56
 
57
- This is the design, not a benchmark. Real throughput and latency depend on your hardware, where your users are, how your data is shaped, and how your handler is written. toil removes the central bottlenecks and keeps per-request cost low; it does not make a slow handler fast or repeal the speed of light between continents.
57
+ This is the design, not a benchmark. Real throughput and latency depend on your hardware, where your users are, how your data is shaped, and how your handler is written. toil removes the central bottlenecks and keeps per-request cost low. It does not make a slow handler fast, and it does not repeal the speed of light between continents.
58
58
 
59
- A few things are honestly staged, not "already everywhere":
59
+ Some parts are honestly staged, not already everywhere.
60
60
 
61
- - The per-request **L1** edge path is live and real. The **L2** regional, **L3** continental, and **L4** global-daemon tiers are opt-in and deployment-gated, not always-on for every app. See the [tiers page](../concepts/tiers.md).
62
- - ToilDB's home-region write model and its core logic are real and tested, but **live multi-cell deployment** (WAN routing, the ScyllaDB backing) is configuration-gated, not on by default. The local dev database is a single in-process store. [How toil is distributed](./distributed.md) is honest about what is finished.
61
+ - The per-request L1 edge path is live and real. The L2 regional, L3 continental, and L4 global-daemon tiers are opt-in and deployment-gated, not always-on for every app. See the [tiers page](../concepts/tiers.md).
62
+ - ToilDB's home-region write model and its core logic are real and tested. Live multi-cell deployment, meaning WAN routing and the ScyllaDB backing, is configuration-gated, not on by default. The local dev database is a single in-process store. [How toil is distributed](./distributed.md) is honest about what is finished.
63
63
 
64
64
  ## Related
65
65