Enclave scaling
How the enclave fleet is provisioned today, what the horizontal scaling story looks like, and what's not yet in place.
Single-AZ, no HA today. The enclave fleet runs in a single Availability Zone with a desired capacity of one instance. There is no active-active setup or cross-AZ failover. This page is honest about what's live versus what's planned.
Current deployment model
The enclave runs as a single EC2 Nitro Enclave instance inside an Auto Scaling Group provisioned by Pulumi (infra/src/resources/asg.ts):
| Parameter | Value |
|---|---|
| Min instances | 0 |
| Desired capacity | 1 |
| Max instances | 2 |
| AZ coverage | Single AZ |
| Health check | EC2 (not ELB) |
| Instance warmup | 120 s |
| Health check grace | 300 s |
Traffic reaches the instance via two load balancers:
- ALB — HTTPS (
:443) for the HTTP API and MCP endpoint - NLB — SMTP (
:25/:465/:587/:2525) for inbound mail
An Elastic IP is attached to the active instance for outbound identity — Sui mainnet, Seal key servers, and Resend all see a stable source IP.
What the ASG is used for today
The ASG exists primarily as a rolling-deploy mechanism, not a scale-out mechanism. When a new EIF (Enclave Image File) is built in CI, the pipeline calls aws autoscaling start-instance-refresh, which replaces the instance in-place with zero-downtime (using minHealthyPercentage: 0 and a rolling strategy). Scaling to max=2 is not triggered automatically — it is a manual ceiling in case a replacement needs to spin up alongside the outgoing instance during a refresh.
What shapes horizontal scaling today
The MCP transport itself does not require sticky routing:
-
Stateless MCP requests. Each
/mcprequest validates its OAuth bearer token against the shared authorization store before dispatching a tool. The enclave keeps no live MCP session or raw bearer-token cache, so revocation applies across every instance without sticky sessions. -
Single Elastic IP. The fleet has one EIP for outbound identity. A second instance would need its own IP allowlisted with upstream services (Seal key servers, Resend), or the fleet would need to NAT outbound traffic through a shared gateway.
The remaining MCP prerequisite is a shared, identity-aware request budget. It must be designed around authenticated mailbox/client identity rather than untrusted forwarding headers before multi-instance traffic is enabled.
Vertical headroom
Before horizontal scale becomes necessary, the instance can be scaled vertically. The enclave allocates CPU and memory from the host at launch (configured via enclave-cpuCount and enclave-memoryMib in the Pulumi stack). The host instance type must have ≥ 4 vCPUs so at least 2 remain for the host OS after enclave allocation.
Staging today runs with 4096 MiB enclave RAM. Production can be bumped to 12288 MiB on the same instance class with a config change and an instance refresh — no code change required.
Defined load test targets
The following targets are defined in the test plan. They establish the expected operating envelope before horizontal scale is needed:
| Scenario | Target |
|---|---|
| Inbound email burst | 1 000 emails / minute, 100% delivery rate |
| Inbound burst p95 latency | < 5 s per email |
| Enclave CPU under burst | < 80% |
| Concurrent decrypt (50 users) | p50 < 2 s, p95 < 5 s, p99 < 10 s |
| Memory pressure (100 × 10 MB attachments) | Graceful degradation above 90% RAM, no OOM crash |
These targets are defined but load tests have not yet been run against a production-equivalent environment. Results will be published here once the load test suite is executed.
The horizontal scaling path (planned)
When traffic warrants it, the path to true horizontal scale is:
- Add a shared MCP rate limiter — enforce one durable budget per authenticated mailbox/client before routing traffic across instances.
- Multi-AZ deployment — extend the ASG subnet list to cover multiple AZs; update the NLB target group accordingly.
- Outbound NAT gateway — replace the per-instance Elastic IP with a NAT gateway so all instances share a stable outbound IP without per-instance allowlisting.
- ELB health checks — switch the ASG health check type from
EC2toELBso instances are only considered healthy once the load balancer confirms they're serving traffic. - CPU/request-based scaling policy — attach a target-tracking policy to the ASG (e.g. target 60% CPU) to trigger scale-out automatically under load.
Related
How is this guide?
Last updated on