VecturaDB on an AWS EC2 instance

One VecturaDB server in your own AWS account, with its data on an EBS volume, HTTPS, API keys, allowed IP addresses and snapshots. From about 12.50 USD a month on your AWS bill.

Disclaimer. This template and its scripts are provided as is, without warranty of any kind, as stated in the Apache License 2.0. The numbers on this page are what we measured with VecturaDB 1.0.0-preview.8 on 6 November 2026 in eu-west-1: your region, sizes, data and versions may behave differently. You are responsible for your data: back it up, and test a restore on a copy before you rely on it.

Not sure about your case? Open an issue in the VecturaDB repository, describe your data and your setup, and we will take a look on a best-effort basis.

What it creates

The template runs VecturaDB 1.0.0-preview.8 (ghcr.io/vecturadb/vecturadb:1.0.0-preview.8), built from Chroma, with sparse vectors, BM25, hybrid search, collection fork and API keys. The same template can also run Chroma 1.5.9, which cannot read the SPANN collections that VecturaDB wrote: see Updates.

VecturaDB keeps the Chroma API: the Chroma clients connect with the URL of the stack and the API key. In our tests the Python client (chromadb 1.5.9) worked over HTTPS with the key, and VecturaDB answered 401 without it.

ResourceNotes
EC2 instance, Ubuntu 24.04Docker runs the server; Caddy serves HTTPS in front of it
EBS data volume, gp3Mounted at /var/lib/chroma; 16 GiB by default, encrypted
Security groupOpens only what the access mode needs
VPC, subnet and internet gateway10.42.0.0/16, in the first availability zone of the region
Elastic IPThe address for HTTPS, and the way out to the package and image registries
IAM role of the instanceSystems Manager runs the configuration and the restore: there is no SSH
Systems Manager documents and associationThe configuration, run at the creation and at every update that changes it; the restore
Secrets Manager secretThe API key
Data Lifecycle Manager policyOnly with backups on: snapshots of the data volume

Deploy

Launch Stack

The button opens the quick-create page of CloudFormation in eu-west-1, with the template of the tag aws-v1.2.2, VecturaDB already chosen and vecturadb as the name of the stack. CloudFormation reads templates from Amazon S3, so the button uses a copy of the template in a public bucket.

  1. Fill the parameters, in three groups: Server (images, instance type, size of the data volume), Access (access mode, allowed IP ranges, API key, domain, email for Let's Encrypt) and Backups. The API key is required for public access.
  2. Under “Capabilities and transforms”, tick the three acknowledgements: IAM resources, IAM resources with custom names, and CAPABILITY_AUTO_EXPAND.
  3. Choose “Create stack”. When the status is CREATE_COMPLETE, the Outputs tab has the Url for the clients.
In our testsTime
Stack from zero, until the server answered over HTTPS521 s

Most of the creation is the first boot of the instance, which installs Docker and Caddy. A new instance in standard credit mode has no CPU credits yet, so it runs at the baseline CPU: in our tests the credit balance was 0 during the first boot.

With the AWS CLI:

aws cloudformation create-stack --region eu-west-1 --stack-name my-vecturadb \
  --template-url https://vecturadb-deploy.s3.eu-west-1.amazonaws.com/aws-v1.2.2/vm/template.yaml \
  --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \
  --parameters ParameterKey=Engine,ParameterValue=vecturadb ParameterKey=ApiKey,ParameterValue=<your key> \
               ParameterKey=Access,ParameterValue=allowed-ips \
               ParameterKey=AllowedIpRanges,ParameterValue=203.0.113.10/32
aws cloudformation wait stack-create-complete --region eu-west-1 --stack-name my-vecturadb
aws cloudformation describe-stacks --region eu-west-1 --stack-name my-vecturadb --query "Stacks[0].Outputs"

The template and its README are in the VecturaDB.Deploy repository, under aws/vm.

Access and HTTPS

AccessWhat is openAddress
Allowed IP addresses443 from your IP ranges; 80 for the certificate onlyhttps://, with the Elastic IP or your domain
Public443 and 80 from anywhere; only with an API keyhttps://
InternalNothing from the internet; port 8000 inside the VPChttp://, on the private address
On the instance, against the server on 127.0.0.1, with the API key (median of 20 runs, t4g.micro)Time
Query2.4 ms
Get2.3 ms
Add of 2 records17.2 ms
8 concurrent writers, in all2.1 s

Cost

The sizes we tested, with the list prices of eu-west-1 in USD for 730 hours a month, on 29 October 2026:

SizeCPU, memoryInstanceRoot volume 8 GiBData volume 16 GiBPublic IPv4Total a month
t4g.micro (default, Arm)2, 1 GiB6.720.701.413.6512.48
t4g.small (Arm)2, 2 GiB13.430.701.413.6519.19

Backups and restore

Restore

  1. Create a volume from a snapshot in the availability zone of the instance, and attach it.
  2. Run the RestoreDocument of the stack: it stops the server, replaces the data with the data of the snapshot, and starts the server again.
  3. Detach and delete the volume.
STACK=my-vecturadb; SNAPSHOT=<snapshot id>
out() { aws cloudformation describe-stacks --stack-name $STACK --query "Stacks[0].Outputs[?OutputKey=='$1'].OutputValue" --output text; }
INSTANCE=$(out InstanceId); DOCUMENT=$(out RestoreDocument)
AZ=$(aws ec2 describe-instances --instance-ids $INSTANCE --query "Reservations[0].Instances[0].Placement.AvailabilityZone" --output text)
VOLUME=$(aws ec2 create-volume --snapshot-id $SNAPSHOT --availability-zone $AZ --volume-type gp3 --encrypted --query VolumeId --output text)
aws ec2 wait volume-available --volume-ids $VOLUME
aws ec2 attach-volume --volume-id $VOLUME --instance-id $INSTANCE --device /dev/sdg
aws ec2 wait volume-in-use --volume-ids $VOLUME
COMMAND=$(aws ssm send-command --document-name $DOCUMENT --instance-ids $INSTANCE --parameters volumeId=$VOLUME --query Command.CommandId --output text)
until aws ssm get-command-invocation --command-id $COMMAND --instance-id $INSTANCE --query Status --output text 2>/dev/null | grep -qE 'Success|Failed|Cancelled|TimedOut'; do sleep 5; done
aws ssm get-command-invocation --command-id $COMMAND --instance-id $INSTANCE --query "[Status,StandardOutputContent]" --output text
aws ec2 detach-volume --volume-id $VOLUME
aws ec2 wait volume-available --volume-ids $VOLUME
aws ec2 delete-volume --volume-id $VOLUME

The data written after the snapshot is lost: take a snapshot first if you may want it back. The data volume stays the same, so the snapshots go on.

In our testsTime
Snapshot by hand, until completed50 s
Volume from the snapshot18-19 s
Attach4-5 s
RestoreDocument, with 5 MB of data10-13 s
Detach and delete21 s

After the restore VecturaDB held the collection of 250 records written before the snapshot, and none of the records written after it. A snapshot taken right after a restore, restored in turn, also held the collection written between the two.

Updates

Delete everything

Deleting the stack deletes the instance, the data volume, the network, the Elastic IP, the roles, the documents and the secret with the API key. The snapshots stay: delete them yourself, after the stack, so that no new snapshot comes after the cleanup.

In the console

  1. In CloudFormation, select the stack, choose Delete and type the name of the stack to confirm.
  2. In EC2, under Snapshots, delete the snapshots with the tag chroma-backup equal to the name of the stack.

With the AWS CLI

aws cloudformation delete-stack --region eu-west-1 --stack-name my-vecturadb
aws cloudformation wait stack-delete-complete --region eu-west-1 --stack-name my-vecturadb
for s in $(aws ec2 describe-snapshots --region eu-west-1 --owner-ids self \
    --filters Name=tag:chroma-backup,Values=my-vecturadb --query "Snapshots[].SnapshotId" --output text); do
  aws ec2 delete-snapshot --region eu-west-1 --snapshot-id $s
done

In our tests the deletion of the stack took 64 seconds, with the CLI, and afterwards nothing of the stack was left in the region, the secret with the API key included.

Limits

VecturaDB is an independent fork of Chroma, under the Apache License 2.0. The original code is copyright Chroma Inc. and its contributors.

Not affiliated with, endorsed by or sponsored by Chroma Inc. CHROMA is a registered trademark of Chroma Inc., used here only to describe compatibility.