Appearance
BYOC on AWS
This brief lists the AWS resources, foundation-model approvals, and the network and identity prerequisites your platform team should arrange so a Nomain BYOC stack can be deployed into your own AWS account from the AWS Marketplace listing. Use it as the conversation-starter when scoping a proof-of-concept or a production rollout.
For the subscribe-and-onboard path, see AWS Marketplace. For network design options, see AWS networking. The Azure equivalent of this brief is BYOC on Azure.
What is Nomain BYOC?
Nomain is an AI-native platform for understanding and modernizing mainframe estates (COBOL, PL/I, JCL, DB2). The BYOC (Bring Your Own Cloud) model runs the entire application stack inside your own AWS account: no Nomain-operated data plane, and no customer code or AST leaves your perimeter.
The stamp makes a small set of outbound calls to Nomain infrastructure, all against the Nomain Customers API and authenticated with an M2M ClientId / Secret issued at customer onboarding. Most are reads (the stamp sends an identifier and receives configuration); the only data it pushes outward is the health heartbeat and, when a user submits it, product feedback:
| # | Call | When and what it does |
|---|---|---|
| 1 | Stamp & tenant configuration (incl. licensing) | At service startup, then per request from cache. Sends the stamp label / tenant id; receives configuration, the signed license JWT (contract tier and expiry), and the Marketplace subscription state. |
| 2 | User count (seats) | On demand (usage insights). Sends the tenant id; only the number of users is read. |
| 3 | Health heartbeat | Every 5 minutes. Sends tenant, cloud, environment, and per-service health (name, status, version), plus three aggregate counters (repositories, systems, and lines of code analyzed) and an aggregate, content-free chat-health summary (counts, percentiles, and each tier's effective model/region; no chat content or PII). |
| 4 | Product feedback | When a user submits feedback in the webapp, the feedback text is proxied through with the user's token. |
Data boundary
These calls carry configuration, license, tenant, health, aggregate-metric, or user-submitted feedback data only. No customer code, AST, embeddings, file names or paths, or analysis results ever crosses this boundary; logs and technical telemetry stay in CloudWatch inside your account.
Architecture at a glance
- One AWS account, one Region. Deploy via the AWS Marketplace CloudFormation template, directly with
aws cloudformation deploy, or from your own Terraform pipeline; see BYOC on AWS with Terraform. - A single VPC holds the entire stack across four subnet tiers per AZ (public for the ALB, private-compute for ECS, private-data for RDS, private-endpoints for AWS-service VPC endpoints).
- All resources lock to private endpoints where AWS supports them. Bedrock, ECR, Secrets Manager, and CloudWatch Logs are reached via interface VPC endpoints; S3 via a gateway endpoint. Bedrock traffic never touches the public Internet.
- Five application services run as ECS Fargate tasks: webapp, graphs-api, chats-api, recipes-api, recipes-worker. The webapp is the only one fronted by the public ALB; the four backends are reachable only from inside the VPC.
- End-user authentication is delegated to your existing OIDC IdP via WorkOS AuthKit, or WorkOS Connect bridging Okta, Entra ID, Auth0, or Keycloak, with no app-level integration changes.
- A topology switch at stack creation selects
single-az(lowest cost) ormulti-az(HA: RDS Multi-AZ standby, a NAT gateway per AZ, and tasks balanced across two AZs).
Solution map
A logical view of the AWS resources Nomain deploys into your account and the outbound calls it makes. Every resource lives inside the customer-owned account boundary. Only the ALB sits in a public subnet, and it gates all external HTTPS traffic through AWS WAF. The stack groups into these areas:
- Compute: ECS Fargate and ECR
- AI / ML: Bedrock
- Database: RDS
- Storage: S3
- Security: Secrets Manager, KMS, IAM
- Messaging and observability: EventBridge, SQS, CloudWatch
- Outbound to Nomain: license validation and heartbeat
Network topology
Every AWS service is fronted by a VPC endpoint (interface or gateway), so the stack speaks to AWS on the AWS backbone. There is no public-Internet path for Bedrock, S3, ECR, Secrets Manager, or CloudWatch Logs. Only the ALB sits in a public subnet, and it gates external HTTPS traffic through AWS WAF. A multi-AZ VPC lays out a public subnet for the ALB, private subnets for ECS and RDS, a dedicated VPC-endpoint subnet for AWS-service connectivity, and a NAT gateway per AZ for outbound egress. The edge is an Internet Gateway with an ACM-issued certificate.
AWS resources provisioned
The CloudFormation stack creates the following resources inside your AWS account. Topology (single-az vs multi-az) is a stack parameter; sizing scales with the EstateSizeBucket parameter (small / medium / large).
| Category | Resource | Detail |
|---|---|---|
| Compute | ECS Fargate cluster + 5 services | webapp, graphs-api, chats-api, recipes-api, recipes-worker (plus Customers API where Marketplace metering is enabled) |
| Container registry | Amazon ECR (private) | image storage, pulled via VPC endpoint |
| Database | RDS PostgreSQL 17 with pgvector | Multi-AZ on multi-az topology; KMS-encrypted; IAM DB Authentication enabled |
| Object storage | Amazon S3 | SSE-KMS bucket for source-code artifacts and generated reports; versioning enabled |
| Foundation model | Amazon Bedrock | via interface VPC endpoint, with no public-Internet egress for inference |
| Async pipeline | EventBridge + SQS + DLQ | recipes-worker job queue and dead-letter for failed analyses; the worker autoscales 0→N tasks on SQS backlog (RecipesWorkerMaxCount, default 5) |
| Ingress | ALB + AWS WAF + Internet Gateway + ACM | public HTTPS termination, managed-ruleset WAF, region-scoped TLS certificate |
| Egress | NAT Gateway (1 per AZ on multi-az) | outbound for Git clones and the Nomain Customers API |
| Network | VPC + 4 subnet tiers per AZ | public, private-compute, private-data, private-endpoints, plus route tables and security groups |
| AWS-service connectivity | VPC endpoints | Bedrock, ECR.api, ECR.dkr, Secrets Manager, CloudWatch Logs (Interface) + S3 (Gateway) |
| Secrets | AWS Secrets Manager | RDS master password, IdP client secret, Nomain-issued M2M credentials |
| Encryption keys | AWS KMS, customer-managed CMKs | at-rest encryption for RDS, S3, EBS, Secrets Manager, SQS |
| Identity | IAM roles (deployer, ECS task and task-execution per service) | least-privilege; no static credentials anywhere in the stack |
| Observability | CloudWatch Logs + Container Insights + RDS Performance Insights | 30-day default retention, CMK-encrypted |
| DNS | Route 53 hosted zone | optional, only if Nomain manages the public DNS name on your behalf |
Bedrock models and quota
The stack requires Bedrock model access in the deployment Region for three models. The default model IDs are bare base-model IDs (e.g. anthropic.claude-sonnet-4-6); the stack normalizes each to the Region's cross-Region inference profile at invoke time, so it still benefits from automatic Region-level load-balancing without customer action. You grant model access on the underlying base model.
| Model ID | Purpose | Used by |
|---|---|---|
| anthropic.claude-sonnet-4-6 | Primary chat & analysis model | chats-api search flows; graphs-api / recipes-worker analysis & process extraction |
| anthropic.claude-haiku-4-5-20251001-v1:0 | Lightweight / fast paths | chat-title classifier; sub-agent triage; low-token utility calls |
| amazon.titan-embed-text-v2:0 | Vector embeddings for pgvector | graphs-api & recipes-worker embeddings (1024 dimensions) |
Service Quotas to raise
The application's built-in token-bucket rate limiter backs off on 429 / throttling, but persistent throttling under typical load means the underlying Bedrock quota is too low. Common starting points:
| Quota name | Default | Suggested for medium estate |
|---|---|---|
InvokeModel RPM, Claude Sonnet | regional default | 1,000 RPM |
InvokeModel TPM, Claude Sonnet | regional default | 1,000,000 TPM |
InvokeModel RPM, Claude Haiku | regional default | 1,000 RPM |
InvokeModel RPM, Titan embeddings | regional default | 2,000 RPM |
First-time Bedrock lead time
First-time Bedrock model access has taken 1-2 business days to approve at Anthropic / AWS in Nomain onboardings to date, longer if it is the first request in the target Region. File the quota requests at the same time so they are approved by the time the stack is ready to deploy.
App-side rate ceilings
Independently of the AWS Service Quotas above, the stack ships per-service Bedrock rate ceilings as stack parameters, so a runaway job cannot burst the whole account's token budget at once. The requests-per-minute defaults are 10,000 (the AWS Bedrock default request quota); the tokens-per-minute defaults are 3,000,000 (the Opus 4.6 floor). Lower them to match your account's applied quota to avoid 429 throttling: a fresh account's granted quota is often far below the published default. Each pair is shared by the graphs-api and recipes-worker tasks (UnusedCodeDetection runs on graphs-api only).
| Parameter pair | Applies to |
|---|---|
LlmServiceMaxRequestsPerMinute / LlmServiceMaxTokensPerMinute | graphs-api & recipes-worker LLM analysis |
AiParserMaxRequestsPerMinute / AiParserMaxTokensPerMinute | AI-assisted (fallback) parsing |
UnusedCodeDetectionMaxRequestsPerMinute / UnusedCodeDetectionMaxTokensPerMinute | dead-code / liveness analysis (graphs-api only) |
Supported AWS Regions
ECR container images are pre-replicated to the eleven Regions below. Deploying outside this set is supported but requires the customer to set up cross-Region image pull (or wait for the next ECR-replication update).
| Group | Regions | Locations |
|---|---|---|
| US | us-east-1, us-east-2, us-west-2 | N. Virginia, Ohio, Oregon |
| EU (DE/FR/UK/IE) | eu-central-1, eu-west-1/2/3 | Frankfurt, Ireland, London, Paris |
| EU (Nordics & CH) | eu-north-1, eu-central-2 | Stockholm, Zurich |
| EU (South) | eu-south-1, eu-south-2 | Milan, Spain |
Not supported: AWS China Regions (cn-north-1, cn-northwest-1), AWS GovCloud, opt-in Regions you have not enabled in your account, and Asia-Pacific Regions until Bedrock GA reaches them with all three required models.
Prerequisites you must provide
| # | Item | Detail |
|---|---|---|
| 1 | AWS account with administrator access for the deployer principal | First-time stack deploy creates IAM roles, KMS keys, and security groups. After bootstrap a scoped service role is sufficient for upgrades. |
| 2 | Deployment Region | One of the eleven Regions listed above with Bedrock GA for all three models. |
| 3 | Bedrock model access | Request via Bedrock Console, Model Access, for anthropic.claude-sonnet-4-6, anthropic.claude-haiku-4-5-20251001-v1:0, amazon.titan-embed-text-v2:0. Allow 1-2 business days for first-time approval. |
| 4 | ACM certificate for DomainName | Issued in the deployment Region; DNS-validated against your DNS zone. (Free with AWS Certificate Manager.) |
| 5 | OIDC IdP application | WorkOS workspace, or your existing Okta / Entra ID / Auth0 / Keycloak wired through WorkOS Connect. |
| 6 | Service Quotas raised | Bedrock RPM / TPM as above; verify Fargate task quota and Elastic IP quota (for NAT gateways) in the target Region. |
| 7 | Customer-managed KMS CMK | One key recommended, shared across RDS, S3, EBS, Secrets Manager, SQS for a single audit / rotation perimeter. |
| 8 | DNS zone control | Optional Route 53 hosted zone, or customer-managed DNS pointing at the ALB DNS name via ALIAS / CNAME. |
| 9 | Cost-management budget | See the cost line items below. |
Identity and access
Inside the stack
- No static credentials. Each ECS service runs under its own least-privilege IAM task role.
- Task execution roles allow only the minimum scope required to pull from ECR, fetch secrets from Secrets Manager, and write to CloudWatch Logs.
- IAM Database Authentication for RDS: services authenticate to Postgres with 15-minute IAM tokens, not long-lived passwords. The RDS master password exists only so the first-deploy bootstrap can create per-service Postgres roles.
- Bedrock invocations are scoped per task role with
bedrock:InvokeModelon the specific model ARNs the service needs.
End-user authentication
- WorkOS AuthKit for end-user OIDC sign-in.
- WorkOS Connect bridges your existing IdP (Okta, Entra ID, Auth0, Keycloak) without app-level changes, so users keep their normal SSO experience. See Single sign-on.
- JWTs are validated locally inside the webapp BFF and each API; there is no per-request callback to WorkOS.
- Outbound M2M credentials issued by Nomain at onboarding cover both license validation and the webapp heartbeat.
Deploy permissions
This is the single reference for what the principal that runs the CloudFormation deploy needs. It covers the internal-stack deploy: an existing customer-managed VPC with an Internal-only webapp (the Model B network layout). If you let the stack create its own VPC (Model A), add the VPC-creation permissions listed on AWS networking.
- The root deploy calls the CloudFormation API (
cloudformation:CreateStack/UpdateStack/DeleteStack/CreateChangeSet/ExecuteChangeSet/DescribeStacks/DescribeStackEvents) withCAPABILITY_NAMED_IAMandCAPABILITY_AUTO_EXPAND(the stack is a root template with nested stacks). - First deploy is privileged, because it creates IAM roles and a KMS key. Use an administrator (or broadly scoped) principal for the initial launch. For upgrades, attach a scoped CloudFormation service role to the stack so the resource permissions live on that role, not on the human/pipeline principal; then routine
UpdateStackneeds only the CloudFormation API plusiam:PassRolefor the service role. iam:PassRoleis required wherever the stack hands a role to a service (ECS task/execution roles, RDS enhanced monitoring, VPC flow logs, EventBridge).
The stack is a set of nested stacks. The permissions each one needs, by AWS service:
| Nested stack | Creates | Deploy permissions (representative) |
|---|---|---|
| security | KMS key + alias, 3 Secrets Manager secrets | kms:CreateKey, CreateAlias, PutKeyPolicy, TagResource; secretsmanager:CreateSecret, TagResource |
| networking | Security groups, VPC endpoints, VPC Flow Log (Model B: no VPC/subnets/NAT/route tables) | ec2:CreateSecurityGroup, AuthorizeSecurityGroup*, CreateVpcEndpoint, CreateFlowLogs; logs:CreateLogGroup; iam:PassRole |
| ai-services | Bedrock interface VPC endpoint, security group, SSM parameters | ec2:CreateVpcEndpoint, CreateSecurityGroup; ssm:PutParameter |
| data | RDS instance + subnet/parameter groups, S3 bucket + policy, monitoring role, log group, security groups | rds:CreateDBInstance, CreateDBSubnetGroup, CreateDBParameterGroup; s3:CreateBucket, PutBucketPolicy, PutEncryptionConfiguration; iam:CreateRole, PassRole; logs:CreateLogGroup; ec2:CreateSecurityGroup |
| iam-task-roles | 6 per-service IAM roles | iam:CreateRole, PutRolePolicy, AttachRolePolicy, TagRole |
| db-setup | Bootstrap Lambda + ECS task/cluster, 2 IAM roles, security group, log group, custom resource | lambda:CreateFunction, InvokeFunction; ecs:CreateCluster, RegisterTaskDefinition, RunTask; iam:CreateRole, PutRolePolicy, PassRole; logs:CreateLogGroup; ec2:CreateSecurityGroup |
| load-balancer | Internal ALB, listeners, target groups, security groups, WAFv2 WebACL (WAF only if enabled) | elasticloadbalancing:CreateLoadBalancer, CreateListener, CreateTargetGroup; ec2:CreateSecurityGroup; wafv2:CreateWebACL, AssociateWebACL (if WAF enabled) |
| messaging | SQS queues + policies, EventBridge bus + rules, an IAM role | sqs:CreateQueue, SetQueueAttributes; events:CreateEventBus, PutRule, PutTargets; iam:CreateRole, PassRole |
| compute | ECS cluster + 5 services + task definitions, autoscaling, Service Discovery namespace, log groups, security groups, alarms | ecs:CreateCluster, CreateService, RegisterTaskDefinition; application-autoscaling:RegisterScalableTarget, PutScalingPolicy; servicediscovery:CreateHttpNamespace; logs:CreateLogGroup; ec2:CreateSecurityGroup, AuthorizeSecurityGroupIngress; cloudwatch:PutMetricAlarm; iam:PassRole |
| observability | CloudWatch alarms + dashboard, SNS topic + subscription | cloudwatch:PutMetricAlarm, PutDashboard; sns:CreateTopic, Subscribe, SetTopicAttributes |
| audit (optional) | Account CloudTrail trail, S3 log buckets, VPC Flow Log, log group, IAM role | cloudtrail:CreateTrail, StartLogging; s3:CreateBucket, PutBucketPolicy; ec2:CreateFlowLogs; logs:CreateLogGroup; iam:CreateRole, PassRole |
Every resource above encrypts at rest with your customer-managed KMS CMK, so the deploy principal also needs kms:Encrypt / GenerateDataKey / CreateGrant on that key. Application services (RDS, ECS, ALB, S3, Secrets Manager, KMS) are created in every network model; only the network layer differs by model. The audit stack is skipped when you disable the per-stamp CloudTrail (an org-level trail covers the account), and the WAFv2 resources when you manage WAF centrally.
Security & compliance
The BYOC posture is built around three properties: your data never leaves your AWS account, no Nomain operator has runtime access to the stack, and every cross-service call uses short-lived identity tokens rather than static credentials. For the cross-cloud security model, see Security.
Defence-in-depth controls
| Layer | What is in place |
|---|---|
| Network isolation | ECS tasks run in private subnets with no public IPs. RDS, Secrets Manager, ECR, Bedrock, and CloudWatch Logs are all reached over VPC endpoints (interface or gateway), so AWS-service traffic stays on the AWS backbone. Only the ALB sits in a public subnet, fronted by AWS WAF with managed rule sets. Outbound egress goes through a single NAT Gateway per AZ. |
| Web Application Firewall | AWS WAF attached to the ALB with AWS-managed rule groups: Core Rule Set, Known Bad Inputs, IP-reputation list, and SQL-injection ruleset. Custom rules can be layered on for geo-blocks or rate-limits. |
| Encryption in transit | TLS 1.2+ enforced on the ALB listener (ACM certificate). The RDS connection uses sslmode=require with the customer CA; Bedrock / S3 / Secrets Manager traffic uses TLS on the AWS backbone. |
| Encryption at rest | All stack resources encrypt at rest with a customer-managed KMS CMK: RDS storage, S3 buckets, EBS volumes, Secrets Manager secrets, and SQS queues. One key is recommended for a single audit / rotation perimeter. |
| Identity | Per-service ECS task IAM roles scoped to exactly what the service needs (Bedrock model ARN, S3 prefix, Secrets Manager secret ARN). Zero static credentials live inside container images or task definitions. Bedrock invocations and S3 access tokens are short-lived STS sessions. |
| Secret management | AWS Secrets Manager is the single source of truth for runtime secrets (Nomain-issued M2M ClientId/Secret, RDS master password for bootstrap, IdP client secret). ECS task definitions reference Secrets Manager ARNs, so no secret value lives in environment variables that could leak via CloudFormation events. |
| End-user authentication | WorkOS AuthKit for OIDC, with WorkOS Connect bridging your existing IdP (Okta / Entra ID / Auth0 / Keycloak) without app-level changes. JWTs validated locally inside the webapp BFF and each API. |
| Tenant data isolation | Within a single BYOC stack, tenant data is scoped through per-service PostgreSQL roles (nomain_chats, nomain_graphs) and row-level filters on tenant ID. Cross-tenant queries are forbidden at the data layer. For full physical isolation, deploy one stack per tenant. |
| Audit logging | Tenant lifecycle events, admin actions, authentication events, and data-deletion events emit through a dedicated audit-category path with stable EventIds, retained for 12 months in a separate CloudWatch log group (vs the 30-day default for operational logs). |
| CloudTrail & activity logs | Account-level CloudTrail (customer-owned) captures every CloudFormation, Secrets Manager, KMS, and IAM API call. The Subscription Activity Log is captured. Alerts route to a customer-specified SNS topic / email list. |
| Vulnerability management | Container images are scanned for CVEs at build time (Trivy). Amazon ECR image scanning (Enhanced Scanning with Inspector) is supported and recommended on the customer ECR repository. |
| Outbound dataflow | The only outbound calls to Nomain infrastructure are license validation and the webapp heartbeat (which now also carries an aggregate, content-free chat-health summary), both carrying license / tenant / aggregate-metric metadata only, with no customer code, AST, embeddings, or chat content. |
What Nomain does not have access to
Nomain has no runtime access to your data plane
- No standing operator credentials into your AWS account. Initial deployment uses an IAM role owned by you, assumed via your own STS process.
- No runtime read or write access to your data plane (RDS, S3, Secrets Manager). Nomain support engineers receive logs and traces only on customer request, through a controlled diagnostics export.
- No telemetry of your source code, AST, embeddings, or chat content back to Nomain.
Compliance alignment
| Area | Position | Detail |
|---|---|---|
| Data residency | Single Region | Every byte (RDS, S3, Bedrock inference via VPC endpoint) stays in the AWS Region you pick at deploy time. EU customers commonly choose eu-west-1 or eu-central-1. |
| DORA / ICT third-party risk | Customer-controlled data plane | Nomain is not a critical ICT service provider for the data plane; it lives in your AWS account. The license and heartbeat call is the only Nomain dependency to model. |
| GDPR / privacy | No PII processed by Nomain | Customer authentication is delegated to your IdP. Nomain stores no end-user PII on its side; tenant-level metadata only flows back via the M2M channel. |
| ISO 27001 / SOC 2 | Audit trail in your account | 12-month retention on audit-category CloudWatch log groups. Customer SIEM ingestion is supported via a Kinesis Firehose subscription on the log group. |
Cost line items
These are the variable-cost categories to model with your AWS account team. Exact numbers depend on your Enterprise / Solutions-Provider pricing and estate size. AWS Marketplace consolidates Nomain subscription metering with infrastructure spend on the same monthly AWS bill.
| Line | Driver |
|---|---|
| ECS Fargate (5 services across 1-2 AZs) | vCPU + GB-month per task; biggest non-AI line |
| RDS PostgreSQL (single-AZ vs Multi-AZ) | Multi-AZ is roughly 2x the single-AZ instance + storage |
| Amazon Bedrock invocations | Dominant variable cost, driven by ingestion + chat volume |
| Amazon S3 | storage GB-month + request rates |
| NAT Gateway (1 per AZ) | per-hour + per-GB processed |
| VPC interface endpoints | per-endpoint per-hour + per-GB processed |
| Application Load Balancer + AWS WAF | ALB capacity units + WAF rule evaluations |
| CloudWatch Logs ingestion + retention | GB ingested + GB-month; tunable via retention setting |
| KMS | per-key per-month + per-API-call (negligible) |
| Marketplace subscription fee | Nomain, metered through AWS Marketplace |
PoC kick-off checklist
When green-lighting a Nomain proof-of-concept on AWS, confirm the following are in place before deployment day:
- AWS account & Region. Account with admin access for the deployer; target Region selected and reviewed against model availability.
- Bedrock model access. Requests filed for the three required models; quota uplifts submitted alongside. Allow 1-2 business days.
- Network. VPC CIDR chosen so it does not overlap with peered accounts / on-prem networks; AZ pair selected for Multi-AZ.
- DNS & ACM. DomainName decided; ACM certificate request issued in the deployment Region; Route 53 ownership or external DNS confirmed.
- Identity provider. WorkOS workspace provisioned (Nomain side); WorkOS Connect to your IdP scoped if you want SSO from day one.
- KMS & secrets. Customer-managed CMK created; Secrets Manager ready to receive the Nomain-issued M2M credentials at first deploy.
- Cost budget. AWS Budgets alerts set against the account; Bedrock token spend modelled separately; Marketplace subscription confirmed.