You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: point scaling limits at Pro, not at this roadmap
`fit.md` told a reader that a request-path rate limiter is a poor actor
and sold the shape that answers it, while `roadmap.md` promised
"distributed rate limits, global admission hooks, and cache-capacity
eviction" in this gem. The two documents gave opposite advice about one
use case, and the roadmap gave a reader a reason to wait for something
this gem should not build.
Each of the three is hot, request-critical, and loss-tolerant, and every
invocation here writes one permanent message row, so the cost model in
`fit.md` already rules out checking on the request path. They are
answered by Solid Objects Pro's grouped and ephemeral operations, and
`fit.md`, `roadmap.md`, and `architecture.md` now say so in the same
words.
Turbo append intents stay an open milestone. They cost nothing at high
QPS, the reactive layer implements every other verb, and the renderer
already emits `turbo-stream action="append"` for batch refreshes and
payload delivery, so what remains is letting an application direct one.
The README listed "Rate limits and account quotas" among the fits. The
low-rate quota is the case that fits, so it reads that way now.
Validation: bundle exec rake (795 runs, 0 failures).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/architecture.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -72,7 +72,7 @@ through the client.
72
72
73
73
### Client and mailbox
74
74
75
-
The client finds or creates the actor instance and atomically allocates a sequence. It inserts one durable message-history row and one ready-membership row. It validates operations and JSON payloads before writing and enforces idempotency-key uniqueness, payload limits, and the per-actor mailbox cap. It also authorizes and coordinates actor destruction. Distributed rate limiting and global admission control are not implemented.
75
+
The client finds or creates the actor instance and atomically allocates a sequence. It inserts one durable message-history row and one ready-membership row. It validates operations and JSON payloads before writing and enforces idempotency-key uniqueness, payload limits, and the per-actor mailbox cap. It also authorizes and coordinates actor destruction. Distributed rate limiting and global admission control are not implemented and are not planned here.
76
76
77
77
Message execution state is table membership, not a status column. The durable message remains for results, retention, and diagnostics. Only live work occupies `ready_messages` or `claimed_messages`, so completed history cannot inflate the polling index.
78
78
@@ -781,11 +781,11 @@ Enqueue counts unfinished rows under the locked actor instance and rejects with
781
781
782
782
### Per-actor rate limits
783
783
784
-
The initial implementation supplies the mailbox cap. Distributed token buckets or time-window counters are a hardening milestone.
784
+
This runtime supplies the mailbox cap. Distributed token buckets and time-window counters are not planned here, because a request-path limiter is hot and loss-tolerant while every invocation writes one permanent message row. Solid Objects Pro answers that shape with grouped and ephemeral operations, which [fit](fit.md) describes.
785
785
786
786
### Global enqueue limits
787
787
788
-
Global admission hooks are not implemented. A future hook can reject based on database health or application policy without introducing a strict global counter as a contention hotspot.
788
+
Global admission hooks are not implemented and are not planned here, for the same reason as per-actor rate limits. A strict global counter would also be a contention hotspot. Reject on database health or application policy in front of the actor instead.
789
789
790
790
### Payload size
791
791
@@ -900,7 +900,7 @@ All backends use unique identity and sequence constraints, short transactions, a
900
900
14.**How does synchronous invocation work across processes?** The caller first tries to claim and execute the actor locally. If another process owns it, a wake-up adapter prompts a durable result query and bounded polling remains the fallback.
901
901
15.**What happens after caller timeout?** A committed message continues and its eventual result can be recovered with the timeout's authorized message reference, or with `find_by` from the request id or the idempotency key when that reference is gone. An enqueue timeout leaves no message. Running Ruby code is not preempted.
902
902
16.**How are results cleaned up?**`prune_messages` deletes eligible terminal history in bounded batches after global or per-actor retention. It previews by default and preserves live work, dead letters, retry links, and unfinished outboxes.
903
-
17.**How are large mailboxes managed?** The implemented controls are the per-actor mailbox cap, payload caps, and fair activation yields; rate and global admission controls remain roadmap work.
903
+
17.**How are large mailboxes managed?** The implemented controls are the per-actor mailbox cap, payload caps, and fair activation yields. Rate and global admission controls are not planned here; Solid Objects Pro answers that shape.
904
904
18.**How are completed messages pruned?** Operators schedule the dry-run-reviewed `prune_messages --execute` command. Solid Objects does not run deletion automatically.
905
905
19.**How are state migrations performed?** Explicit one-step actor migrations on activation, persisted only with a successful fenced commit.
906
906
20.**What happens during rolling deploys?** Newer state can make old workers incompatible; deploys must preserve backward readability or drain old workers.
0 commit comments