Conversation
Add opt-in clustered routing, durable checkpoints, guarded manual and automatic ECS scaling, protocol limits, and serialized local autosaves. Cover ownership transfer, recovery, and deployment settings with integration tests and an authenticated load workload. Refs #455.
Deployment and runtime verification — 2026-09-11Verified commit Existing-installation upgradeThe existing ECS service had Availability Zone Rebalancing ENABLED. ECS rejected the update to The existing service upgraded in place, first to the new standalone task and then to cluster mode with one worker. Both rollouts completed with healthy ALB targets and zero failed tasks. The frontend was deployed with Deployment scope: applies used reviewed, saved Terraform plans scoped to the Yjs module through Deployed checks
Cold recovery procedure: blocked REST requests only for the disposable draft after it loaded, inserted CloudWatch export covered 11:38:01–12:13:23 UTC, with 110 worker metric samples: summed Scripts and checksOn Node 24:
Remaining validation and final state
|
Deployed load verification after
|
| Mode | CPU units / MiB per worker | Clients / documents | Generated writes | Reconnects | Propagation p95 / p99, ms | Result |
|---|---|---|---|---|---|---|
| Standalone | 256 / 512 | 100 / 25 | 17,900 | 0 | 236 / 359 | Pass |
| Standalone | 256 / 512 | 100 / 1 | — | — | — | Aborted: worker health failure |
| Standalone | 1024 / 2048 | 100 / 25 | 17,900 | 0 | 211 / 285 | Pass |
| Cluster, one worker | 1024 / 2048 | 100 / 25 | 17,900 | 0 | 167 / 231 | Pass |
| Standalone | 1024 / 2048 | 100 / 1 | 17,900 | 0 | 603 / 772 | Pass |
| Cluster, one worker | 1024 / 2048 | 100 / 1 | 17,900 | 0 | 674 / 1286 | Pass |
All successful steady workloads had zero persistence errors and zero rejected connections in their collected CloudWatch samples. In cluster mode, the committed S3 versions referenced by DynamoDB contained all 100 writers and exactly 17,900 writes for both workloads. Standalone runs created no binary Yjs manifests, as expected.
The 256 / 512 hot-document run saturated CPU at approximately 100%, reached approximately 23.4 seconds of event-loop delay, and lost ALB health. The load process was stopped; no final convergence or latency JSON was emitted. Memory remained low. The same workload completed in both modes at 1024 / 2048, with peak one-minute average CPU around 26%.
The larger standalone comparisons used a temporary task definition changing the cluster flag while retaining the same image, CPU, memory, networking, and existing checkpoint storage. The earlier normal standalone Terraform deployment was also verified. No saved cluster tables or snapshots were deleted to perform the mode comparison.
These are single-run measurements from one client host across the network, not production capacity guarantees. Hot-document latency samples are capped by the workload at the first 1,000,000 observations. One hot document still has one owner; adding workers distributes documents rather than splitting that document.
Continuous editing through manual scaling
Ran 100 clients / 25 documents for 720 seconds, changing worker count 1 → 2 → 4 → 2 through reviewed count-only Terraform plans and scripts/deploy-terraform.sh. Every worker kept 1024 CPU units / 2048 MiB and the same image.
- All requested worker counts reached healthy ALB targets and active membership. Live document ownership was 25 on one worker, then 13/12, then 8/7/6/4, then 14/11. Private forwarding was observed.
- Final result: 100 connected, converged, 71,371 generated writes. All 25 committed snapshots contained all 100 writers and exactly 71,371 writes.
- Observed 420 reconnects: 184 closes with code 1012, 58 with code 4401, and 178 with code 1006. The run crossed scope-token expiry and successfully reauthorized/reconnected. Client writes pause while disconnected, so this result is not uninterrupted availability.
- Across 54 collected worker metric samples, CloudWatch recorded three persistence errors and 137 rejected connection attempts. The checkpoint failures were transaction conflicts; final durable state recovered. This is a convergence/durability pass with an availability caveat, not a zero-error scaling run.
- Received-update propagation p95/p99 was 154/224 ms. That statistic does not represent time spent disconnected. Peak sampled event-loop p99 was about 45.7 ms; no queued output bytes were observed.
Browser and identity checks
Both modes passed checks with two distinct temporary Cognito identities: bidirectional presence, concurrent edits, presence removal on disconnect, and rejection (403) when one user's scope token was paired with the other user's JWT. Both users could access only the disposable test space and received 403 from the admin-user API.
On the fixed deployed image, two additional browser tabs shared a separate draft during the live load run. They recovered all earlier markers, synchronized new edits in both directions, displayed live presence, and accepted an edit during shrink without reloading. The latest markers matched both the business record and committed checkpoint; all four original fixtures remained drafts and matched their snapshots. No workflow was started.
After restoring development sizing and replacing the worker, a fresh browser navigation recovered all latest markers and connected successfully. The temporary browser account was then signed out, and both test tabs were closed.
Final state and remaining limits
Restored the saved dev configuration: cluster mode, one worker, 256 CPU units / 512 MiB, fixed image 21f3b79b0d27db31, ECS task definition revision 27. ECS desired/running = 1/1, pending = 0, deployment completed, one healthy ALB target/member, Availability Zone Rebalancing disabled, and all four Yjs alarms OK. Both DynamoDB tables are ACTIVE. The two temporary standalone task definitions are inactive; existing tables and checkpoints were retained.
Both temporary Cognito accounts were signed out globally and deleted, with deletion verified. The private credential directory was removed. Two membership entries remain in the disposable test space: removing those entries requires permission to use the existing owner browser session, which is pending. Test drafts were retained for inspection.
Abrupt owner death, injected AWS storage outages, and metric-driven autoscaling were not exercised in AWS. Graceful replacement, manual scaling, and the local fault coverage should not be read as proof of those scenarios.
Deployment used Yjs-scoped recovery plans. Full-stack reconciliation remains outstanding: the broader plan includes unrelated Lambda updates and deletion of an older AgentCore image still referenced by runtime version 100. That cleanup was not applied. No merge was performed.
The current Yjs service keeps collaboration state in one task, so increasing concurrent editors can exhaust that task. Adding independent replicas would split live document state. This change adds opt-in document ownership and durable recovery so documents can be distributed across ECS tasks with manual or automatic scaling.
Closes #455.
Implementation
maximumPercent = 100deployment configuration.Validation
3c18aadd.25f62548. The unchanged root dependency tree has existing audit findings.25f62548. The same workload then converged with zero reconnects; a bounded AWS transaction probe completed 24/24 operations successfully after the fix.Detailed procedure, measurements, failures, and cleanup status: #457 (comment)
Rollout and limitations
Cluster mode remains disabled by default. Production standalone sizing increases from 512 CPU units / 1024 MiB to 1024 / 2048; explicit overrides can retain the previous allocation. Other environments retain 256 / 512.
Enable cluster mode with exactly one worker first, verify persisted recovery, then increase the manual count. Exercise growth, shrinkage, owner failure, and storage errors in an isolated deployment before enabling automatic scaling. The single-worker transition briefly interrupts collaboration.
Horizontal scaling distributes documents; one hot document still has one owner. The two-second checkpoint interval is not a guaranteed recovery-point objective during storage failures. Snapshot retention and permanent deletion need an explicit policy before using cluster mode for data that must be erased with its parent.
Configuration, rollback steps, metrics, and the load workload are documented in
docs/development/yjs-operations.md.