Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Changelog

## Unreleased

- Align the use-case claims with the Ruby gem. The README table sold per-key
rate limits, while the Ruby fit guide called a rate limiter an anti-pattern.
Both projects now draw one line: a low-rate quota that a reminder refills
fits, because each check is one durable ordered message, and a limiter that
every request touches does not.
- Point the high-QPS reader at [Solid Objects Pro](https://solidobjects.pro/)
from the rate-limit sentence in the README and `docs/fit.md`, and name what
it adds for that shape: grouped commits and ephemeral operations. The README
states that it ships for the Rails gem today and that the Node build is in
development.
- Move the early-release caveat off the first screen. It is now a `Status`
section at the end of the README, with a table-of-contents entry, which
matches where the Ruby gem keeps the same statement. The first screen keeps
the transaction caveat, because that one changes whether a reader should
install anything.
- State the workflow limit next to the workflow row instead of only in
`docs/fit.md`. A workflow fits when one entity owns the mutable state and its
mailbox holds the step order. A durable execution engine that replays named
steps from a step log is a different tool.

## 0.14.3 - 2026-08-25

- Rewrite the first screen around the objection a reader actually has. The
Expand Down
43 changes: 28 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,6 @@ durable actor state in the origin's private file system, and its offline
writes can replay onto a Node **or Rails** backend over one shared wire
contract. See [Solid Objects in the browser](#solid-objects-in-the-browser).

> **Early release:** the correctness core has automated coverage. That coverage
> includes the supported databases, the Chromium browser client, the browser
> runtime, process recovery, and the packaged artifacts. The TypeScript
> implementation is still new. There is one deployed first-party reference
> application. There is no measured scale and no third-party production use
> yet. Read the
> [delivery boundaries](#delivery-boundaries) before you use it for important
> data.

> **Not a replacement for SQL transactions:** when one row update inside one
> transaction solves the problem, use that and install nothing. Solid Objects
> earns its cost when the critical section outlives the transaction: a hold that
Expand All @@ -56,6 +47,7 @@ contract. See [Solid Objects in the browser](#solid-objects-in-the-browser).
- [Operations](#operations)
- [Design provenance](#design-provenance)
- [Documentation](#documentation)
- [Status](#status)
- [License](#license)

## The programming model
Expand Down Expand Up @@ -177,7 +169,7 @@ committed state are the same argument.
Not worth it for a plain counter, a single-row update inside one transaction, a
stateless job, bulk ingestion or a data-parallel pipeline, CPU-heavy work, a
large JSON document that belongs in normalized rows, globally placed edge
state, or a global rate-limit counter that every request touches. One hot
state, or a rate-limit counter that every request touches. One hot
identity is serialized on purpose, so making everything one identity makes a
queue. Split an identity only when the domain can tolerate independent
ordering and transactions.
Expand Down Expand Up @@ -221,15 +213,26 @@ Durable Objects:
| Multiplayer, presence, or collaboration | Room, session, or document | Joins, moves, and edits commit in order; subscribers refresh from committed state |
| Reservations and expiring holds | Show, resource, or stock item | Availability checks and holds cannot interleave; a durable reminder can release an old hold |
| Checkout and account workflows | Cart, order, account, device | The current step, retries, and effect results return to the same ordered mailbox |
| Per-key rate limits | API key, account, or device | Token checks and decrements are serialized; a reminder can refill the bucket |
| Quotas and expiring limits | API key, account, or device | Low-rate quota checks and decrements are serialized; a reminder can refill the bucket |
| Stateful agent sessions | Agent session | Messages and tool results apply in order and pending work survives a worker exit |

The common shape is one durable coordination boundary with an application
defined identity. Work for that identity is serialized, while unrelated rooms,
carts, accounts, or sessions can progress concurrently. A single global rate
limiter or another very hot identity is a poor fit because it becomes an
intentional bottleneck. If one ordinary row transaction solves the problem,
prefer that. See [Choosing Solid Objects](docs/fit.md) for the longer guide.
carts, accounts, or sessions can progress concurrently. Any very hot identity is
a poor fit, because it becomes an intentional bottleneck.

Two of those rows have a limit. A quota fits when one identity checks it a few
times per minute, because each check is one durable ordered message with a
retained history row. A limiter that every request to that identity touches
does not fit here. That high-QPS shape is what
[Solid Objects Pro](https://solidobjects.pro/) targets.

A workflow fits when one entity owns the mutable state and its mailbox holds
the step order. A durable execution engine that replays named steps from a step
log is a different tool.

If one ordinary row transaction solves the problem, prefer that. See
[Choosing Solid Objects](docs/fit.md) for the longer guide.

## Measured behavior

Expand Down Expand Up @@ -540,6 +543,16 @@ TypeScript package in the deployed Node and SQLite topology above.
- [Contributing](CONTRIBUTING.md)
- [Security policy](SECURITY.md)

## Status

**Early release:** the correctness core has automated coverage. That coverage
includes the supported databases, the Chromium browser client, the browser
runtime, process recovery, and the packaged artifacts. The TypeScript
implementation is still new. There is one deployed first-party reference
application. There is no measured scale and no third-party production use yet.
Read the [delivery boundaries](#delivery-boundaries) before you use it for
important data.

## License

Solid Objects is released under the [MIT License](MIT-LICENSE).
10 changes: 9 additions & 1 deletion docs/fit.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,16 @@ history, and no actor-state migration contract.
identities.
- Compute and state must be automatically placed close to clients at the edge.
- The team wants a managed control plane to place, scale, and recover workers.
- A rate limiter sits on the request path, and every request touches the same
identity. A low-rate quota that a reminder refills is a different case and
fits, because each check is one durable ordered message. For the high-QPS
limiter, see [Solid Objects Pro](https://solidobjects.pro/): grouped commits
coalesce concurrent writes into one insert, and ephemeral operations keep
loss-tolerant calls out of the durable journal. It ships for the Rails gem
today, and the Node build is in development.
- Durable workflow replay across named steps is more important than a mutable
object with ordered operations.
object with ordered operations. The runtime redelivers an ordered message and
retries it. It does not replay a function from a step log.

## Model identities deliberately

Expand Down