Your own AWS account
This page is about the third stack: Metergraph running on ECS Fargate in one AWS account you own, deployed by Terraform. It is not the open source server, and it is not the customer-local bundle. None of the commands on those sections apply here.
One installation belongs to one AWS account. There is no control plane, no replication, no licensing callback, and no Metergraph operator access across the boundary. Traces and provider credentials stay in that account.
The capability delta is the thing to read first
Section titled “The capability delta is the thing to read first”A BYOC installation runs with METERGRAPH_DEPLOYMENT_PROFILE=byoc-core, and
that profile is what gates the product. Gating is by deployment profile, not by
plan: capabilities.py:8-41 defines two sets, and the managed set has 19
capabilities where byoc-core has 8.
These eight are present:
telemetry, alerts, api_keys, membership, workspace_settings_read,
reports, analysis_runs, optimization.
So ingest (native and OTLP), pricing and enrichment, the spend, performance and trace views, API keys, the six deterministic detectors, alert listing and acknowledgement, membership reads, analysis runs, and report viewing and export all work exactly as they do on the hosted service.
Everything else fails closed. A request to an absent capability returns 404
with code: capability_unavailable and the capability’s name, from a
middleware that runs before routing. It is a 404 rather than a 403 on purpose:
the surface does not exist in this deployment.
| Route prefix | Capability | Why it is absent |
|---|---|---|
POST /v1/auth/signup, /v1/organization/invitations | signup | Operators provision identities in Cognito, so there is no public signup or invitation flow |
PATCH /v1/organization | workspace_settings | Settings are readable, not writable |
/v1/upgrade-requests | billing | Nothing is billed by Metergraph |
/v1/catalog, /v1/admin | platform_admin | The global model and pricing catalog editor is a hosted surface |
/v1/campaign, /v1/sme-reviews, /v1/judge-qualifications | evaluations | Evaluation authoring is a hosted surface |
/v1/dataset | datasets | |
/v1/simulation, /v1/tool-replay-cache | simulations | |
/v1/canaries | canaries | |
/v1/recommendation-deliveries, /v1/github-installations, /v1/email, /internal/deliveries, /internal/github | external_delivery | Slack, GitHub and email delivery run from Metergraph’s own infrastructure |
/v1/provider-batch | provider_probes | |
/v1/agent | agent_api | The MCP server is not available here |
/v1/import-sync | import_sync | Scheduled import sync is a hosted surface |
Three more are gated by shape rather than prefix, in the same file:
POST /v1/reports/{id}/approveandPOST /v1/recommendations/{id}/approveneedexternal_delivery, so approving a recommendation into a pull request is unavailable.POST /v1/recommendations/{id}/canaryneedscanaries./v1/routes/{route}/constraintsand/v1/routes/{route}/evaluationneedevaluations.
The worker is gated too: under byoc-core it accepts only the ingest_batch
and detector_scan job kinds.
An operational kill switch is separate from all of this and answers 503, not
404. A 404 capability_unavailable means the capability is not part of the
deployment; a 503 means the deployment is deliberately paused.
What Terraform creates
Section titled “What Terraform creates”| Concern | AWS service |
|---|---|
| Compute | ECS Fargate: API, worker, and one-off admin and analysis tasks |
| Ingress | Internal ALB, your ACM certificate, a Route 53 private record |
| Dashboard | The React build, served by the API image on the same hostname |
| Database | RDS PostgreSQL 17, Single-AZ, point-in-time recovery |
| Objects and queue | Versioned KMS-encrypted S3, SQS with a native dead-letter queue |
| Analysis | A Bedrock-only pipeline profile in an isolated one-off Fargate task, through a module-created private Bedrock Runtime endpoint |
| Identity | A dedicated Cognito user pool with self-registration off |
| Secrets | Secrets Manager, with scoped task roles per service |
| Operations | CloudWatch logs, metrics and alarms under your CMK |
Workloads have no public IP. The deployment runs one API replica and one worker replica after bootstrap, and offers no availability SLA or zone-failure continuity.
Runtime egress
Section titled “Runtime egress”Default runtime egress is TCP/443 through a security group you own, so it can be logged and filtered by your existing controls.
| Destination | Path | Needed by |
|---|---|---|
| The private PostgreSQL endpoint | VPC | API, worker, migration, analysis |
| S3, SQS, Secrets Manager, KMS, CloudWatch | VPC endpoints where configured | every runtime task |
| Amazon Bedrock Runtime | The module’s private interface endpoint | the analysis task |
| Your regional Cognito issuer and domain | Logged NAT or firewall | browser login and API token exchange |
public.ecr.aws | Logged NAT or firewall | platform image pull |
No external model provider, email, Slack, GitHub, analytics, licensing or
Metergraph control-plane destination is part of byoc-core. Model traffic for
an analysis stays on the Bedrock private endpoint.
Module inputs
Section titled “Module inputs”The module has no defaults for the things that describe your account, so a plan fails until you supply them.
| Required input | What it is |
|---|---|
region, vpc_id, private_subnet_ids | At least two private subnets, for the ALB and RDS subnet groups |
private_zone_id, private_hostname | The private Route 53 zone and the name the ALB answers on |
certificate_arn, kms_key_arn | Your ACM certificate and your customer-managed key |
image, analysis_runner_image | Both are validated against @sha256: and refused unless pinned by manifest digest |
bedrock_model_resource_arns | The exact foundation-model and inference-profile ARNs the analysis task may invoke. Must be non-empty and must all start with arn:aws...:bedrock: |
cognito_user_pool_domain_prefix | The hosted login domain prefix |
alarm_sns_topic_arn | Where CloudWatch alarms go |
egress_security_group_id | Your logged TCP/443 egress security group |
The ones worth knowing about among the defaulted inputs:
| Input | Default | Note |
|---|---|---|
analysis_pipeline_builder_model | us.anthropic.claude-sonnet-5 | The model that writes the analysis |
analysis_pipeline_max_generation_cost_usd | 200 | A worst-case cap on one run’s generation cost. Must be greater than zero |
automatic_analysis_enabled | true | Scheduling keeps its call-count, complete-day, cooldown, spacing and daily-cap policy |
retention_days | 90 | Relational trace data and every object version expire on this schedule |
backup_retention_days | 7 | |
log_retention_days | 30 | |
api_desired_count, worker_desired_count | 0 | Deliberately zero, so the first apply creates the infrastructure before anything runs against an unmigrated database |
image_architecture | ARM64 | Or X86_64 |
enable_delete_protection | true | Keys, database and buckets survive an ordinary terraform destroy |
break_glass_allow_destroy | false | The deliberate override for the above |
analysis_runner_anthropic_api_key_secret_arn, ..._openai_... and
..._google_... are optional Secrets Manager ARNs. Each is injected into the
analysis task under the provider’s own variable name, and is read only by
search-enabled workloads. Leave them empty and they are omitted.
Bringing up a workspace
Section titled “Bringing up a workspace”There is no public signup here, so the first workspace and its owner are
created by an operator against an exact OIDC identity. Cognito is the issuer,
and the immutable (identity_issuer, identity_subject) pair is what grants
access. Email and display name are presentation data and grant nothing.
-
Apply the module
Section titled “Apply the module”The outputs you will need afterwards are
private_url,ecs_cluster_arn,migration_admin_task_definition_arn,admin_network_configurationandsmoke_test_command. -
Run the migration and admin task
Section titled “Run the migration and admin task”The admin task definition runs
python -m metergraph_app.cliwith the database owner role and alist-tenantsdefault command. Every operator command is a container override on that task definition, launched into the subnets and security groups fromadmin_network_configuration:aws ecs run-task \--cluster "$CLUSTER_ARN" \--task-definition "$ADMIN_TASK_DEFINITION_ARN" \--launch-type FARGATE \--network-configuration "$ADMIN_NETWORK_CONFIGURATION" \--overrides '{"containerOverrides":[{"name":"admin","command":["python","-m","metergraph_app.cli","list-tenants"]}]}' -
Create the first workspace and its owner
Section titled “Create the first workspace and its owner”python -m metergraph_app.cli bootstrap-workspace <slug> \--identity-subject <cognito-sub> \--email owner@example.com \--display-name "Owner Name"It refuses if the slug exists, or if that email or identity pair is already registered.
--identity-issuerdefaults to the deployment’s configured issuer. -
Add the rest of the team
Section titled “Add the rest of the team”python -m metergraph_app.cli grant-member <slug> \--identity-subject <cognito-sub> \--email member@example.com \--role memberRoles are
owner,memberandviewer. -
Prove ingest end to end
Section titled “Prove ingest end to end”The
smoke_test_commandoutput gives you the exact invocation. It submits one native and one OTLP GenAI trace with a disposable ingest key, and refuses to run at all unless the target reportsdeployment_profile=byoc-core.python scripts/byoc_smoke.py --base-url https://<private-hostname> \--token "$METERGRAPH_APP_TOKEN"Confirm both smoke routes appear in the dashboard, then revoke the key.
More operator commands, the RLS check, backups and the tenant purge are on Operations.
Content and retention
Section titled “Content and retention”Content capture defaults on, and the per-event opt-out strips content before it
is stored. Relational trace and call data, and every current and historical
object version, expire after retention_days. Operational logs keep
log_retention_days. What the SDK sends and what is stored are two different
limits: see Content and privacy.