MAILGATE  DOCS
Reference

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):

ParameterValue
Min instances0
Desired capacity1
Max instances2
AZ coverageSingle AZ
Health checkEC2 (not ELB)
Instance warmup120 s
Health check grace300 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:

  1. Stateless MCP requests. Each /mcp request 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.

  2. 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:

ScenarioTarget
Inbound email burst1 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:

  1. Add a shared MCP rate limiter — enforce one durable budget per authenticated mailbox/client before routing traffic across instances.
  2. Multi-AZ deployment — extend the ASG subnet list to cover multiple AZs; update the NLB target group accordingly.
  3. 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.
  4. ELB health checks — switch the ASG health check type from EC2 to ELB so instances are only considered healthy once the load balancer confirms they're serving traffic.
  5. 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.

How is this guide?

Last updated on

On this page