Redash Setup
Deploy Redash on AWS ECS (Fargate) — IaC Specification
A complete resource specification for deploying Redash on AWS ECS Fargate. Feed this to an AI and ask it to generate Terraform, CDK (TypeScript), Pulumi, or CloudFormation — all the details it needs are here.
Architecture
ECS Fargate Task (single task, two containers sharing localhost)
├── Redash container (:5000) ──► RDS PostgreSQL (:5432)
└── Redis container (:6379, sidecar)
Image source: Docker Hub (default) or Amazon ECR (recommended for production).
What Each Service Does
Amazon ECS (Elastic Container Service) — AWS's container orchestration service. It runs your Docker containers without you managing servers. Fargate is the serverless mode — you just say "run this container with X CPU and Y memory" and AWS handles the rest.
AWS Fargate — The compute engine behind ECS that removes the need to manage EC2 instances. You define your container, Fargate provisions the server, runs it, and scales it. You pay only for the CPU/memory your containers use.
Amazon RDS (Relational Database Service) — A managed PostgreSQL database. AWS handles patching, backups, and failover. Redash uses this to store its own metadata — user accounts, saved queries, dashboard definitions, and settings.
Redis — An in-memory key-value store. Redash uses it as a message broker and cache — it queues background jobs (like running queries) and caches results. We run it as a sidecar container inside the same Fargate task, so it communicates with Redash over localhost.
Amazon ECR (Elastic Container Registry) — AWS's private Docker image registry. Instead of pulling images from Docker Hub (public internet), you push them to ECR and pull from within AWS — faster, no rate limits, and you control exactly which version is deployed.
AWS Secrets Manager — A service that stores passwords, API keys, and other secrets securely. Instead of hardcoding your database password in the task definition, you store it in Secrets Manager and ECS pulls it at runtime.
Application Load Balancer (ALB) — Sits in front of your ECS containers and distributes incoming traffic. Required for HTTPS (SSL), custom domains, and running multiple Redash containers for high availability.
ACM (AWS Certificate Manager) — Provides free SSL/TLS certificates for your domain. You attach the certificate to the ALB so users access Redash over HTTPS.
IAM (Identity and Access Management) — AWS's permission system. The ECS task execution role gives your containers permission to pull images from ECR, read secrets from Secrets Manager, and write logs to CloudWatch.
CloudWatch Logs — AWS's log aggregation service. Container stdout/stderr is streamed here so you can debug issues without SSH-ing into anything.
VPC (Virtual Private Cloud) — Your isolated network in AWS. Security groups act as firewalls — you define which ports are open and who can access what. RDS lives in private subnets (no internet access), ECS lives in public subnets (or behind an ALB).
Region
ap-northeast-1 (Tokyo) All resources should be created in this region.
Resource 1 — VPC & Networking
Use the default VPC or create a new one with the following:
-
2 Availability Zones minimum
-
Public subnets (for ECS tasks with public IP)
-
Private subnets (for RDS)
-
1 NAT Gateway if using private subnets for ECS (set to 0 if using public subnets to save cost)
-
Internet Gateway attached
Resource 2 — Security Groups
ECS Security Group (redash-ecs-sg)
| Direction | Port | Source | Purpose |
| Inbound | 5000 | 0.0.0.0/0 (or restrict to your IP/CIDR) | Redash Web UI |
| Outbound | All | 0.0.0.0/0 | Internet + DB access |
RDS Security Group (redash-rds-sg)
| Direction | Port | Source | Purpose |
| Inbound | 5432 | Reference redash-ecs-sg by security group ID | ECS → Database |
| Outbound | All | 0.0.0.0/0 | Default |
Resource 3 — Secrets (AWS Secrets Manager)
Secret 1: Database Credentials
-
Secret name:
redash/db-credentials -
Auto-generate password: Yes, 30 characters, exclude punctuation
-
Username:
redash
Secret 2: Redash Secret Key
-
Secret name:
redash/secret-key -
Auto-generate: Yes, 64 characters, exclude punctuation
Resource 4 — RDS PostgreSQL
| Setting | Value |
| Identifier | redash-analysis-db |
| Engine | PostgreSQL 15 |
| Instance class | db.t3.micro (see pricing guide to pick by team size) |
| Allocated storage | 20 GB |
| Storage type | gp3 |
| Database name | postgres |
| Credentials | From Secrets Manager (redash/db-credentials) |
| VPC subnets | Private subnets |
| Security group | redash-rds-sg |
| Multi-AZ | No (single AZ for cost saving) |
| Public access | No |
| Backup retention | 7 days |
| Deletion protection | No for dev, Yes for production |
| Removal policy | Destroy for dev, Retain for production |
Resource 5 — ECS Cluster
| Setting | Value |
| Cluster name | redash-analysis-cluster |
| Infrastructure | AWS Fargate (serverless, no EC2 instances) |
Resource 6 — IAM Task Execution Role
| Setting | Value |
| Role name | ecsTaskExecutionRole |
| Trusted entity | AWS service → ECS Tasks |
| Managed policy | AmazonECSTaskExecutionRolePolicy |
| Additional permissions | secretsmanager:GetSecretValue for both secrets above |
Resource 7 — ECS Task Definition
| Setting | Value |
| Family | redash-analysis-task |
| Launch type | Fargate |
| OS / Architecture | Linux / X86_64 |
| CPU | 1024 (1 vCPU) — see pricing guide to adjust |
| Memory | 2048 MB — see pricing guide to adjust |
| Task execution role | ecsTaskExecutionRole |
| Network mode | awsvpc (default for Fargate) |
Container 1: Redash
| Setting | Value |
| Name | redash |
| Image | redash/redash:latest (Docker Hub) or ECR URI |
| Essential | Yes |
| Port | 5000/tcp |
| Memory hard limit | 1536 MB |
| Memory soft limit | 1024 MB |
| Logging | CloudWatch Logs, stream prefix redash, retention 14 days |
Environment variables:
| Key | Value | Source |
REDASH_DATABASE_URL | postgresql://redash:\<PASSWORD>@<RDS_ENDPOINT>:5432/postgres | Constructed from Secrets Manager + RDS endpoint |
REDASH_REDIS_URL | redis://localhost:6379/0 | Hardcoded (Redis is a sidecar in the same task) |
PYTHONUNBUFFERED | 0 | Hardcoded |
REDASH_SECRET_KEY | Value from redash/secret-key | Secrets Manager |
Container 2: Redis
| Setting | Value |
| Name | redis |
| Image | redis:7-alpine (Docker Hub) or ECR URI |
| Essential | No |
| Port | 6379/tcp |
| Memory hard limit | 512 MB |
| Memory soft limit | 256 MB |
| Logging | CloudWatch Logs, stream prefix redis, retention 14 days |
| Environment variables | None |
Resource 8 — ECS Service
| Setting | Value |
| Service name | redash-analysis-service |
| Cluster | redash-analysis-cluster |
| Task definition | redash-analysis-task (latest revision) |
| Launch type | Fargate |
| Desired count | 1 |
| Subnets | Public subnets (same VPC as RDS) |
| Security group | redash-ecs-sg |
| Auto-assign public IP | Yes |
| Min healthy percent | 0 |
| Max healthy percent | 200 |
| Deployment type | Rolling update |
Connectivity rules (applied after service creation)
-
Allow inbound on port 5000 from 0.0.0.0/0 to ECS service
-
Allow ECS service to reach RDS on port 5432
(Optional) Resource 9 — ECR Repositories
Only needed if you want to host images privately instead of pulling from Docker Hub.
| Repository | Image to push | Tag |
redash | redash/redash:latest | latest or pin a version like 10.1.0 |
redis | redis:7-alpine | 7-alpine |
Enable scanOnPush: true for vulnerability scanning.
When using ECR, update the container image URIs in the task definition to:<ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/redash:\<TAG>
(Optional) Resource 10 — Application Load Balancer (Production)
Skip this for dev/testing. Required for production, HTTPS, and horizontal scaling.
ALB
| Setting | Value |
| Name | redash-alb |
| Scheme | Internet-facing |
| Type | Application (ALB) |
| VPC | Same VPC as ECS and RDS |
| Subnets | Public subnets (at least 2 AZs) |
| Security group | redash-alb-sg (see below) |
ALB Security Group (redash-alb-sg)
| Direction | Port | Source | Purpose |
| Inbound | 80 | 0.0.0.0/0 | HTTP (redirect to HTTPS) |
| Inbound | 443 | 0.0.0.0/0 | HTTPS |
| Outbound | 5000 | redash-ecs-sg | ALB → ECS |
When using ALB, update the ECS Security Group (redash-ecs-sg)
| Direction | Port | Source | Purpose |
| Inbound | 5000 | redash-alb-sg (by security group ID, not 0.0.0.0/0) | ALB → ECS only |
| Outbound | All | 0.0.0.0/0 | Internet + DB access |
Target Group
| Setting | Value |
| Name | redash-tg |
| Target type | IP (required for Fargate) |
| Protocol | HTTP |
| Port | 5000 |
| VPC | Same VPC |
| Health check path | /ping |
| Health check expected response | 200 OK (returns PONG) |
| Healthy threshold | 3 |
| Unhealthy threshold | 3 |
| Health check interval | 30 seconds |
| Health check timeout | 10 seconds |
| Deregistration delay | 60 seconds |
Listener — HTTPS (port 443)
| Setting | Value |
| Port | 443 |
| Protocol | HTTPS |
| Certificate | ACM certificate for your domain (e.g., redash.yourcompany.com) |
| Default action | Forward to redash-tg |
Listener — HTTP (port 80)
| Setting | Value |
| Port | 80 |
| Protocol | HTTP |
| Default action | Redirect to HTTPS (port 443, status 301) |
ACM Certificate
| Setting | Value |
| Domain | Your domain (e.g., redash.yourcompany.com) |
| Validation method | DNS (add the CNAME record to your DNS provider) |
| Region | ap-northeast-1 (must match ALB region) |
DNS (Route 53 or external DNS)
Create an A record (alias) or CNAME pointing your domain to the ALB DNS name.
ECS Service changes when using ALB
When ALB is enabled, update Resource 8 (ECS Service) with:
| Setting | Value |
| Auto-assign public IP | No (ALB handles public access) |
| Subnets | Private subnets (with NAT Gateway for outbound) |
| Load balancer | Attach redash-alb |
| Target group | redash-tg |
| Container name | redash |
| Container port | 5000 |
Post-Deploy Steps
Without ALB (dev/testing)
-
Find the public IP in ECS Console → Cluster → Tasks → Networking
-
Health check:
http://<PUBLIC_IP>:5000/ping→ returnsPONG -
Open Redash:
http://<PUBLIC_IP>:5000 -
First boot takes 5–15 minutes (database migrations)
-
Create admin account, set org name, add data sources
With ALB (production)
-
Wait for ALB target group to show the target as healthy
-
Health check:
https://redash.yourcompany.com/ping→ returnsPONG -
Open Redash:
https://redash.yourcompany.com -
First boot takes 5–15 minutes (database migrations)
-
Create admin account, set org name, add data sources
Updating Redash
-
If using ECR: pull new image locally, tag, push to ECR
-
Create a new revision of the task definition with the updated image
-
Update the ECS service to use the new revision (or force new deployment)
-
ECS handles rolling deployment automatically
Troubleshooting
Task keeps restarting: Check CloudWatch Logs. Usually wrong DB password or RDS security group not allowing port 5432 from ECS.
Redis connection refused: Both containers must be in the same task definition. Redis URL must be redis://localhost:6379/0.
Can't reach port 5000: Confirm public IP is assigned, task is in a public subnet, and ECS security group allows inbound 5000.
Long loading on first boot: Normal — Redash runs database migrations. Wait 10–15 minutes.
Scaling
-
Horizontal: Increase
desired countin the ECS service to run multiple Redash tasks (needs an ALB in front to distribute traffic) -
Vertical: Increase CPU/memory in a new task definition revision — update the service to pick up the new revision
-
Database: Change the RDS instance class (causes a brief downtime during modification)
Backup & Recovery
-
RDS automated backups are enabled (7-day retention as configured above) — supports point-in-time recovery
-
Export important Redash dashboards and queries periodically via the Redash UI
-
Document all data source connection strings — these live inside Redash's DB, not in your IaC
Security Best Practices
-
RDS: Never expose to public internet (
publicAccess: false) -
Secrets: Always use AWS Secrets Manager for DB password and Redash secret key — never hardcode in task definitions
-
Network: Use private subnets for RDS; consider private subnets + ALB for ECS in production
-
IAM: Use least-privilege task execution roles
-
Images: Pin specific image versions instead of
latestfor reproducibility -
Monitoring: Enable CloudWatch Container Insights on the ECS cluster for CPU/memory/network metrics
-
HTTPS (production): Place an Application Load Balancer with an ACM certificate in front of the ECS service; restrict the ECS security group to only accept traffic from the ALB
Pricing Guide — ap-northeast-1 (Tokyo)
Tokyo region is roughly 15–20% more expensive than us-east-1. Prices below are on-demand estimates.
RDS PostgreSQL — Pick by team size
| Instance | vCPU | RAM | Best For | Hourly (Tokyo) | Monthly (Tokyo) |
db.t3.micro | 2 | 1 GB | 1–3 users, testing | ~$0.022 | ~$16 |
db.t3.small | 2 | 2 GB | 3–10 users | ~$0.044 | ~$32 |
db.t3.medium | 2 | 4 GB | 10–30 users | ~$0.088 | ~$64 |
db.t3.large | 2 | 8 GB | 30–100 users | ~$0.176 | ~$128 |
db.r6g.large | 2 | 16 GB | 100+ users, production | ~$0.270 | ~$197 |
Add ~$2.40/month per 20 GB gp3 storage.
ECS Fargate — Pick by team size
Fargate pricing in Tokyo: ~$0.05056/vCPU/hour + ~$0.00553/GB/hour.
| Config | Best For | Monthly (Tokyo) |
| 0.25 vCPU / 0.5 GB | Personal use, 1–2 users | ~$11 |
| 0.5 vCPU / 1 GB | 2–5 users | ~$22 |
| 1 vCPU / 2 GB | 5–15 users | ~$44 |
| 2 vCPU / 4 GB | 15–50 users | ~$88 |
| 4 vCPU / 8 GB | 50+ users | ~$176 |
Total Estimated Monthly Cost (Tokyo)
| Environment | RDS | ECS | Other | Total |
| Personal / testing | db.t3.micro (~¥2,400) | 0.5 vCPU / 1 GB (~¥3,300) | — | ~¥5,700 (~$38) |
| Small team (5–15) | db.t3.small (~¥4,800) | 1 vCPU / 2 GB (~¥6,600) | — | ~¥11,400 (~$76) |
| Medium team (15–50) | db.t3.medium (~¥9,600) | 2 vCPU / 4 GB (~¥13,200) | ALB ~¥3,000 | ~¥25,800 (~$172) |
| Large team (50+) | db.t3.large (~¥19,200) | 4 vCPU / 8 GB (~¥26,400) | ALB + HTTPS ~¥3,750 | ~¥49,350 (~$329) |
JPY estimates assume ~¥150/USD. Actual rates fluctuate. ECR storage is negligible (~$0.10/GB/month). Verify current pricing via the AWS Pricing Calculator.
How Everything Connects — Full Flow Diagram
Dev/Testing Setup (no ALB)
Internet
│
▼
┌───────────────┐
│ Public IP │
│ :5000 │
└───────┬───────┘
│
┌─────────────▼──────────────┐
│ ECS Fargate Task │
│ (Public Subnet) │
│ │
│ ┌────────┐ ┌──────────┐ │
│ │ Redash │◄─►│ Redis │ │
│ │ :5000 │ │ :6379 │ │
│ └───┬────┘ └──────────┘ │
│ │ (localhost) │
└──────┼──────────────────────┘
│
│ Port 5432
▼
┌──────────────┐
│ RDS │
│ PostgreSQL │
│ (Private │
│ Subnet) │
└──────────────┘
Production Setup (with ALB + HTTPS)
Internet
│
┌─────▼──────┐
│ Route 53 │ redash.yourcompany.com
└─────┬──────┘
│
┌───────▼────────┐
│ ALB │
│ :443 (HTTPS) │──── ACM Certificate
│ :80 → 301 │
│ (Public │
│ Subnets) │
└───────┬────────┘
│
│ Port 5000 (internal)
▼
┌─────────────────────────────┐
│ ECS Fargate Task │
│ (Private Subnet) │
│ │
│ ┌────────┐ ┌──────────┐ │
│ │ Redash │◄──►│ Redis │ │
│ │ :5000 │ │ :6379 │ │
│ └───┬────┘ └──────────┘ │
│ │ (localhost) │
└──────┼───────────────────────┘
│
│ Port 5432
▼
┌──────────────┐ ┌──────────────────┐
│ RDS │ │ Secrets Manager │
│ PostgreSQL │ │ - DB password │
│ (Private │ │ - Redash secret │
│ Subnet) │ └──────────────────┘
└──────────────┘
┌──────────────────┐
┌──────────────┐ │ CloudWatch Logs │
│ ECR │ │ - redash logs │
│ (optional) │ │ - redis logs │
└──────────────┘ └──────────────────┘
Request Flow (step by step)
1. User opens https://redash.yourcompany.com
│
2. DNS (Route 53) resolves to ALB
│
3. ALB terminates SSL, forwards HTTP to Target Group on port 5000
│
4. Target Group routes to Redash container's private IP
│
5. Redash container processes the request:
├── Reads/writes metadata → RDS PostgreSQL (port 5432)
├── Queues background jobs → Redis (localhost:6379)
└── Returns HTML/JSON to user via ALB
│
6. User sees the Redash dashboard
Security Group Flow
Internet ──► ALB SG (allow 80, 443) ──► ECS SG (allow 5000 from ALB SG only) ──► RDS SG (allow 5432 from ECS SG only)