Deploy DIAL on AWS
Deploy the full DIAL stack to Amazon EKS using the umbrella Helm chart, with Amazon S3 for storage and Amazon Bedrock as the model provider. This guide assumes you operate an EKS cluster and are familiar with Helm and kubectl. For the chart model and infrastructure mapping, read the Helm chart overview first.
Prerequisites
-
An EKS cluster, version 1.24 or higher, with
kubectland Helm 3.8.0 or higher configured against it -
The AWS Load Balancer Controller installed in the cluster
-
An S3 bucket for DIAL file storage
-
Amazon Bedrock enabled in your target region, with access granted to at least one model
-
IAM roles for service accounts (IRSA) for DIAL Core's S3 and Bedrock access
-
An Amazon Cognito user pool with an app client and a hosted UI domain, for DIAL Chat sign-in
-
An ACM certificate for your domain (for HTTPS ingress)
-
The DIAL Helm repository added:
helm repo add dial https://charts.dialx.ai
helm repo update
Step 1: Create a values file
Start from the upstream AWS simple example and fill in your environment. The required values are:
core:
# IRSA role granting access to the S3 bucket
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: <AWS_CORE_ROLE_ARN>
env:
aidial.storage.bucket: <AWS_CORE_S3_BUCKET_NAME>
aidial.identityProviders.cognito.jwksUrl: "https://cognito-idp.<AWS_COGNITO_REGION>.amazonaws.com/<AWS_COGNITO_ID>/.well-known/jwks.json"
aidial.identityProviders.cognito.rolePath: "cognito:groups"
aidial.identityProviders.cognito.issuerPattern: '^https:\/\/cognito-idp\.<AWS_COGNITO_REGION>\.amazonaws\.com.+$'
ingress:
enabled: true
ingressClassName: alb
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/healthcheck-path: /health
alb.ingress.kubernetes.io/certificate-arn: <AWS_CERTIFICATE_ARN>
alb.ingress.kubernetes.io/ssl-redirect: "443"
hosts:
- dial.<DOMAIN>
bedrock:
# IRSA role granting access to Amazon Bedrock
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: <AWS_BEDROCK_ROLE_ARN>
env:
aidial.bedrock.region: <AWS_BEDROCK_REGION>
chat:
env:
AUTH_CALLBACK_BASE_URL: "https://chat.<DOMAIN>"
AUTH_POST_LOGOUT_REDIRECT_URI: "https://chat.<DOMAIN>"
DIAL_CORE_URL: "http://dial-core.dial.svc.cluster.local"
CORS_ORIGIN: "https://chat.<DOMAIN>"
secrets:
AUTH_SESSION_SECRET: <AUTH_SESSION_SECRET>
AUTH_COGNITO_CLIENT_ID: <AUTH_COGNITO_CLIENT_ID>
AUTH_COGNITO_HOST: <AUTH_COGNITO_HOST>
AUTH_COGNITO_SECRET: <AUTH_COGNITO_SECRET>
ingress:
enabled: true
ingressClassName: alb
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/healthcheck-path: /api/health
alb.ingress.kubernetes.io/certificate-arn: <AWS_CERTIFICATE_ARN>
alb.ingress.kubernetes.io/ssl-redirect: "443"
hosts:
- chat.<DOMAIN>
DIAL Core and DIAL Chat each get their own Ingress under core.ingress and chat.ingress, so the AWS Load Balancer Controller provisions one ALB per service. The upstream example adds further ALB tuning (target-group stickiness, HTTP/2, a pinned TLS policy) that this snippet omits for brevity; see the AWS example - simple for the full set.
core.env registers Cognito as the identity provider DIAL Core trusts for user tokens; chat.env/chat.secrets configure DIAL Chat's own sign-in flow against the same user pool. In your Cognito app client, set the allowed callback and sign-out URLs to match AUTH_CALLBACK_BASE_URL.
Replace the placeholders:
<AWS_CORE_ROLE_ARN>— IRSA role ARN for S3 access<AWS_CORE_S3_BUCKET_NAME>— the S3 bucket name<AWS_COGNITO_REGION>— the AWS region of your Cognito user pool<AWS_COGNITO_ID>— the Cognito user pool ID<AWS_BEDROCK_ROLE_ARN>— IRSA role ARN for Bedrock access<AWS_BEDROCK_REGION>— the region where Bedrock models are available<DOMAIN>— your base domain; DIAL Core is exposed atdial.<DOMAIN>and DIAL Chat atchat.<DOMAIN>, for exampleexample.com<AUTH_COGNITO_CLIENT_ID>— the Cognito app client ID<AUTH_COGNITO_HOST>— the Cognito hosted UI domain, for examplehttps://your-domain.auth.<AWS_COGNITO_REGION>.amazoncognito.com<AUTH_COGNITO_SECRET>— the Cognito app client secret<AUTH_SESSION_SECRET>— a random secret DIAL Chat uses to encrypt session cookies<AWS_CERTIFICATE_ARN>— the ACM certificate ARN for HTTPS
Generate the DIAL API key, encryption key, cache password, and <AUTH_SESSION_SECRET> before installing and supply them as values or Kubernetes secrets.
Step 2: Install the chart
helm install dial dial/dial \
-f values.yaml \
--version <CHART_VERSION> \
--namespace dial \
--create-namespace
Pin <CHART_VERSION> to a released chart version.
Step 3: Verify the deployment
Check that the pods are running:
kubectl get pods -n dial
Once both ALBs have addresses, DIAL Chat is reachable at https://chat.<DOMAIN>/; open it in a browser and sign in through your Cognito user pool. Confirm the Unified API responds:
curl https://dial.<DOMAIN>/openai/deployments \
-H "Api-Key: <YOUR_DIAL_API_KEY>"
Result
DIAL Core, DIAL Chat, Valkey, and the Bedrock adapter run on your EKS cluster, with files persisted to S3 and models served from Bedrock.
Note
The
bedrockalias of thedialchart deploys the standalone Bedrock adapter, which will be deprecated. DIAL Model Provider replaces it. Deploy it with the DIAL Extension chart and move your models as described in Migrate from the standalone adapters.
Production architecture
The simple example is a starting point. For a production deployment, size the AWS services and configure redundancy as follows.
Recommended service tiers
| AWS service | Configuration / tier |
|---|---|
| Amazon EKS | Standard, zone-redundant |
| Elastic Load Balancing (ALB) | Standard |
| Amazon S3 | S3 Standard, with Multi-Region Access Points |
| ElastiCache | Standard, Multi-AZ |
| Amazon Bedrock | Sized to capacity requirements; usage-based pricing |
Dependencies whose technology may follow corporate standards:
| Dependency | AWS service |
|---|---|
| SSO | Amazon Cognito |
| Firewall | AWS WAF with ALB or CloudFront, plus VPC security groups |
| Logging and monitoring | Amazon CloudWatch and AWS CloudTrail |
| Container registry | Amazon ECR |
| Secret storage | AWS Secrets Manager |
Scalability
DIAL services are stateless, so they run as multiple concurrent copies. As a baseline, run two copies of each service on different nodes for high availability. The services are not resource-intensive and handle thousands of users without further scaling.
To absorb load spikes, configure autoscaling for DIAL Core based on CPU usage (for example, scale out when usage exceeds 80% of the CPU limit for one minute), and enable cluster autoscaling so new nodes are added when existing nodes lack capacity.
Scaling language models is the more common need, because a single Bedrock model instance is often capped by request rate limits. Options, in order of preference:
- Request a regional quota increase through the AWS Service Quotas console or AWS Support.
- Invoke models in additional regions, optionally with cross-region inference.
- Use multiple AWS accounts to access model endpoints.
High availability
Achieve high availability through Multi-AZ deployments: run DIAL service copies across availability zones and use highly available configurations for the supporting services.
| Service | Availability SLA | Resilient to zone-wide outages |
|---|---|---|
| Amazon EKS | 99.95% | Yes, if configured explicitly |
| AWS IAM | 99.0%–99.99% | Yes |
| Amazon S3 | 99.9% | Yes, with multi-region replication |
| ElastiCache (Redis OSS) | 99.99% with Multi-AZ | Yes, if configured explicitly |
| Amazon Bedrock | 99.9% | Depends on configuration |
| AWS Secrets Manager | 99.99% | Yes |
| Amazon ECR | 99.9% | Yes (regional) |
Because Bedrock availability depends on configuration, define multiple model endpoints in different regions. If one region becomes unavailable, DIAL automatically tries the next endpoint in the list.
Disaster recovery
DIAL has two parts with separate recovery policies: DIAL Core and the optional DIAL Analytics.
DIAL Core consists of stateless services plus a single permanent store on S3 (ElastiCache is a cache and can be safely restarted). For a region-wide failure:
- S3 — use Cross-Region Replication or Multi-Region Access Points for built-in cross-region redundancy. After a regional failure, review and re-establish the multi-region configuration as needed.
- All other services — being stateless, redeploy the full set in a secondary region and re-route the DIAL domain name to the new entry point. To meet a tight recovery time objective, keep a passive DIAL Core deployment in the secondary region and activate it on failure.
When the primary region is restored, there is no need to fail back.
DIAL Analytics keeps ingested rows in ClickHouse and its catalog of tables, pipelines, saved queries, and dashboards in PostgreSQL. Back up PostgreSQL to keep those definitions. Replicate the usage-log blobs it reads like any other permanent store: the backfill endpoint can re-ingest a date range from them, up to BACKFILL_MAX_DAYS days per request.
Further reading
- Deploy Bedrock models — register Amazon Bedrock models and grant IAM access
- Custom Apps deployment — deploy your own applications alongside DIAL
- Run DIAL with high availability — replicas, zone spread, and failover settings in the Helm chart
- Azure deployment — the equivalent guide for Azure AKS
- GCP deployment — the equivalent guide for Google GKE
- Deploy DIAL on a generic Kubernetes cluster — deploy DIAL to any Kubernetes cluster