Skip to content

AWS Marketplace deployment

EvidentSource is distributed through the AWS Marketplace as a container product. Subscribing gives you the container image, in the Marketplace’s registry, and a CloudFormation template that deploys it into your own AWS account.

Your data stays in your account.

The template deploys into infrastructure you already have. You need:

  • A VPC, with:
    • private subnets for the servers, with outbound access through a NAT gateway. The servers pull images, reach S3, check their license with AWS License Manager, report usage to AWS Marketplace Metering, send traces and metrics to AWS X-Ray and CloudWatch, and, with RequireAuth on, fetch your identity provider’s key set from JwtJwksEndpoint. Without a NAT, every one of those needs a VPC endpoint or another route (the key set is on the identity provider’s network, not AWS’s), and the collector image (AdotCollectorImage) needs mirroring into a private registry;
    • subnets for the load balancer: public ones for an internet-facing load balancer, private ones for an internal one;
    • the route tables of the private subnets.
  • An Availability Zone that supports S3 Express One Zone, for the write-ahead log, with your private subnets in or routable to it.
  • An ACM certificate covering the API hostname, and the MCP hostname if you deploy MCP.
  • The container image URI from the listing’s fulfillment options.
  • An ECS cluster on Fargate, with a service running the EvidentSource servers, and an OpenTelemetry collector alongside each, sending traces to AWS X-Ray and metrics to CloudWatch.
  • A license check: the servers validate your Marketplace entitlement with AWS License Manager at startup, and refuse to start without one.
  • An MCP service, optional, running the MCP server at its own hostname.
  • An Application Load Balancer, with listeners on 443 for HTTPS and on 50051 for gRPC over TLS, plus 80, which redirects to HTTPS. MCP traffic is routed to its service by hostname.
  • Two buckets:
    • an S3 bucket for the data: versioned, encrypted, and closed to public access;
    • an S3 Express One Zone directory bucket for the write-ahead log, in the Availability Zone you choose;
    • both retained when the stack is deleted.
  • A gateway VPC endpoint for S3 Express, so the servers reach it without a NAT.
  • Service discovery in a private DNS namespace, which the servers use to find each other.
  • IAM roles for the tasks, and a CloudWatch Logs log group.
  • Route 53 records, if you give a hosted zone.
ParameterDefaultWhat
VpcIdrequiredThe VPC to deploy into
PrivateSubnetIdsrequiredSubnets for the servers
PublicSubnetIdsrequiredSubnets for the load balancer
PrivateRouteTableIdsrequiredRoute tables of the private subnets, for the S3 Express endpoint
AvailabilityZoneIdrequiredThe Availability Zone ID for the write-ahead log bucket, such as use1-az4
CertificateArnrequiredThe ACM certificate
DomainNamerequiredThe hostname for the HTTP and gRPC API
ContainerImagerequiredThe image URI from the listing
AlbSchemeinternalinternal, or internet-facing
RequireAuthtrueRequire authentication on every request
JwtIssuer, JwtJwksEndpointemptyThe issuer every token must carry, and its key set. The server and the load balancer verify tokens against it. Required when RequireAuth is true. See Security
JwtAudienceemptyOne printable ASCII audience, or dedicated Cognito app client ID; no commas or whitespace. Required when RequireAuth is true
JwtAudienceModeaud-arrayaud-string, aud-array, or cognito-access (client_id plus token_use=access), checked at both ALB and server
TaskCpu8192CPU units per server: 1024, 2048, 4096, 8192 or 16384
TaskMemory32768Memory per server in MB: 2048, 4096, 8192, 16384, 32768 or 65536
NodeDesiredCount1Number of servers: 0 to 10
DeployMcptrueDeploy the MCP service. The server verifies the token it forwards; see Security
AdotCollectorImagethe public ECR imageThe OpenTelemetry collector image; mirror it into a private registry when the servers have no NAT
McpDomainNameemptyThe MCP hostname; required when DeployMcp is true
HostedZoneIdemptyA Route 53 hosted zone for DNS records; leave empty to point your own DNS at the load balancer
EnvironmentNameproductionA suffix for resource names
LogRetentionDays90Log retention

The template’s defaults are one server, with 8 vCPU and 32 GB of memory.

  • Don’t go below the default CPU lightly. A server divides its CPUs between its network runtime and its query runtime, and at 2 vCPU the network side starves under load.
  • Memory feeds the storage cache: SlateDB’s cache takes 70% of it.
  • Servers are interchangeable, so scale by changing NodeDesiredCount. Each database’s writes go to one server at a time, so a single database’s write throughput doesn’t grow with the server count; many databases spread across servers. Set NodeDesiredCount to 0 to pause the deployment.

See Tuning for the settings that trade throughput against S3 cost.

To upgrade, update the stack with the new version’s ContainerImage URI.

Upgrading past the metering checkpoint cutover

Section titled “Upgrading past the metering checkpoint cutover”

Usage metering keeps its own small store in S3, under metering/slatedb, recording how far each database has been billed. One release changed the shape of what it keeps — the checkpoints now identify a database by its storage identity, so a database that is deleted and created again under the same name starts counting from zero instead of resuming the old one’s progress.

There is no migration: the two shapes cannot be read as each other, and guessing would either bill history twice or stop billing it at all.

Servers refuse to start against a checkpoint store they cannot read. The startup log then says what was found and repeats the instruction below. That refusal is deliberate: metering reads this store once an hour, and a server that started anyway would report nothing, hour after hour, with nothing but a log line to show for it.

To clear it:

  1. Set NodeDesiredCount to 0 and wait for the tasks to stop.
  2. Delete everything under the metering/slatedb/ prefix in the stack’s S3 bucket. Nothing else under that bucket is metering state, and nothing there is your data.
  3. Update ContainerImage and set NodeDesiredCount back.

The first cycle after that baselines every database at its current revision and bills nothing for the history already written; usage is metered from there on.

To check a deployment’s metering pipeline without waiting for the hourly cycle, run the server image with --meter-once: it runs one cycle and exits. The codes it reports deliberately:

CodeMeaning
0A healthy cycle.
1The cycle failed, or the server could not start far enough to run one. Usually transient — the store was unreachable, a database could not be read — but a bad configuration also lands here, so read the log before retrying rather than looping.
2This image was built without usage metering compiled in. Not a deployment you can meter.
3AWS refused the usage record. Usually a task role without aws-marketplace:MeterUsage, or an account that is not subscribed.
4The checkpoint store holds state this build cannot read — the cutover above.

Startup can also fail hard enough to panic before a cycle begins, which exits 101. Treat any code the table does not list as a failed run, not as an unknown-but-fine one.

Only 0 means usage was metered. A case $? gate that treats anything else as success reports a run that never happened.