> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cloud Deployment (AWS)

> Deploy KaireonAI to your own AWS account with App Runner, Supabase, and Upstash — an Enterprise self-managed deployment under a commercial license.

<Note>
  This guide describes deploying KaireonAI into **your own AWS account** — an Enterprise self-managed deployment under a commercial license. Container images are provisioned as part of an Enterprise agreement. If you would rather we run it for you, use the fully hosted **Cloud** plan or a **Dedicated** single-tenant instance — see [Deployment options](/self-host/deploy/options).
</Note>

This guide covers deploying KaireonAI using a managed cloud stack in your own account — no servers to maintain, automatic scaling, and managed databases.

## Architecture

```mermaid theme={null}
graph TD
    subgraph runner["AWS App Runner"]
        APP["KaireonAI (Next.js)<br/>kaireon-api container"]
    end

    APP --> DB[("Supabase<br/>(PostgreSQL)")]
    APP --> CACHE[("Upstash<br/>(Redis)")]
    APP -.->|"image pull"| ECR["Amazon ECR<br/>(Images)"]

    style runner fill:#1e1b4b,stroke:#6366f1,color:#e0e7ff
    style APP fill:#312e81,stroke:#818cf8,color:#c7d2fe
    style DB fill:#065f46,stroke:#10b981,color:#d1fae5
    style CACHE fill:#7c2d12,stroke:#f97316,color:#fed7aa
    style ECR fill:#1e3a5f,stroke:#60a5fa,color:#bfdbfe
```

## Production Stack

| Service                | Provider              | Purpose                           | Pricing             |
| ---------------------- | --------------------- | --------------------------------- | ------------------- |
| **App Runtime**        | AWS App Runner        | Hosts the Next.js application     | Pay per vCPU/memory |
| **Database**           | Supabase (PostgreSQL) | Primary data store via Prisma 7   | Free tier available |
| **Cache**              | Upstash (Redis)       | Enrichment caching, rate limiting | Free tier available |
| **DNS**                | Route 53              | Domain management                 | \~\$0.50/zone/month |
| **CDN**                | CloudFront            | Marketing site + static assets    | Pay per request     |
| **Container Registry** | Amazon ECR            | Docker image storage              | Pay per GB          |

## Step-by-Step Setup

<Steps>
  <Step title="Create a Supabase project">
    1. Go to [supabase.com](https://supabase.com) and create a new project
    2. Choose a region close to your App Runner deployment
    3. Copy the **Connection string** (Settings → Database → URI)
    4. The format is: `postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres`

    <Warning>
      Use the **Session mode** connection string (port 5432), not the pooler (port 6543), for Prisma migrations. App Runner can use either.
    </Warning>
  </Step>

  <Step title="Create an Upstash Redis database">
    1. Go to [upstash.com](https://upstash.com) and create a new Redis database
    2. Choose the same region as your Supabase project
    3. Copy the **Redis URL** (starts with `rediss://`)
    4. Upstash provides TLS by default — the `rediss://` protocol handles encryption
  </Step>

  <Step title="Push Docker image to ECR">
    ```bash theme={null}
    # Authenticate with ECR
    aws ecr get-login-password --region us-east-1 | \
      docker login --username AWS --password-stdin <YOUR_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com

    # Build from the platform/ directory (which contains the Dockerfile) and push
    cd platform
    docker build -t kaireon-api .
    docker tag kaireon-api:latest <YOUR_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/kaireon-api:latest
    docker push <YOUR_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/kaireon-api:latest
    ```
  </Step>

  <Step title="Create App Runner service">
    1. Go to the AWS App Runner console
    2. Choose **Container registry → Amazon ECR** as the source
    3. Select the `kaireon-api` repository and `latest` tag
    4. Configure:
       * **CPU:** 1 vCPU (or 2 for production)
       * **Memory:** 2 GB (or 4 for production)
       * **Port:** 3000
    5. Add environment variables:

    ```
    DATABASE_URL=postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres
    REDIS_URL=rediss://default:[password]@[host].upstash.io:6379
    NEXTAUTH_SECRET=[generate-a-secure-random-string]
    NEXTAUTH_URL=https://your-domain.com
    NODE_ENV=production
    ```
  </Step>

  <Step title="Initialize the database">
    Run migrations against your Supabase database from your local machine:

    ```bash theme={null}
    DATABASE_URL="postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres" \
      npx prisma db push
    ```

    <Warning>
      Run `prisma db push` **only against a fresh, empty database**. It drops any table not defined in `schema.prisma` — including the `ds_*` customer-schema tables and `_flow_*` pipeline staging tables created at runtime — which means data loss on a populated database. For an existing deployment, evolve the schema by applying the numbered files in `prisma/manual-sql/` with `psql` instead. Supabase requires SSL, so append `?sslmode=require` to the `DATABASE_URL` when running `psql`.
    </Warning>

    Then seed the admin user:

    ```bash theme={null}
    DATABASE_URL="postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres" \
      npx tsx prisma/seed.ts
    ```
  </Step>

  <Step title="Configure custom domain (optional)">
    1. In App Runner, go to **Custom domains** and add your domain
    2. Create a CNAME record in Route 53 pointing to the App Runner URL
    3. App Runner automatically provisions and renews TLS certificates
  </Step>
</Steps>

## Updating

To deploy a new version:

```bash theme={null}
# Build with git SHA tag (from the platform/ directory, which contains the Dockerfile)
SHA=$(git rev-parse --short HEAD)
cd platform
docker build -t kaireon-api .
docker tag kaireon-api:latest <YOUR_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/kaireon-api:$SHA
docker tag kaireon-api:latest <YOUR_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/kaireon-api:latest
docker push <YOUR_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/kaireon-api:$SHA
docker push <YOUR_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/kaireon-api:latest
```

App Runner automatically redeploys when you push a new image (if auto-deployment is enabled), or you can trigger a manual deployment from the console.

## Monitoring

* **App Runner logs** — Available in the App Runner console or CloudWatch
* **Supabase dashboard** — Monitor database connections, query performance, and storage
* **Upstash dashboard** — Monitor Redis commands, memory usage, and latency

## Required Environment Variables (Production)

In addition to the core variables shown above, production deployments on App Runner should include these security-related variables. The platform validates them at startup and will refuse to start if they are missing:

```
JWT_SIGNING_SECRET=[generate-a-secure-random-string-min-32-chars]
CONNECTOR_ENCRYPTION_KEY=[32-byte-hex-key-for-credential-encryption]
WEBHOOK_SIGNING_SECRET=[random-string-for-signing-outbound-webhooks]
API_KEY_PEPPER=[random-string-for-api-key-hashing]
CORS_ALLOWED_ORIGINS=https://your-domain.com
```

See the [full environment variable reference](/self-host/deploy/options#environment-variables) for all available configuration.

## Troubleshooting

<AccordionGroup>
  <Accordion title="ECR authentication expired ('no basic auth credentials')">
    ECR login tokens expire after 12 hours. Re-authenticate before pushing:

    ```bash theme={null}
    aws ecr get-login-password --region us-east-1 | \
      docker login --username AWS --password-stdin <YOUR_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com
    ```

    If using CI/CD, ensure your pipeline refreshes the token on each run.
  </Accordion>

  <Accordion title="App Runner service fails to start (health check timeout)">
    App Runner expects the application to respond on the configured port within 120 seconds. Common causes:

    * **Missing environment variables** — The platform validates `DATABASE_URL` and production secrets at startup. Check the App Runner logs in CloudWatch for `[env-validation] Missing required environment variables`.
    * **Insufficient memory** — The Next.js build requires at least 2 GB. For production, allocate 4 GB.
    * **Database unreachable** — Ensure the Supabase connection string uses the direct connection (port 5432), not the pooler, and that the App Runner VPC can reach the database.
  </Accordion>

  <Accordion title="Database connection errors ('connection refused' or 'timeout')">
    Supabase databases may require SSL. Ensure your `DATABASE_URL` includes `?sslmode=require` if connecting from App Runner:

    ```
    DATABASE_URL=postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres?sslmode=require
    ```

    Also verify the connection string uses the correct port (5432 for session mode, 6543 for transaction pooler).
  </Accordion>

  <Accordion title="App Runner deployment stuck in 'Operation in progress'">
    App Runner deployments can take 5-10 minutes. If stuck beyond 15 minutes, check CloudWatch logs for the service. You may need to cancel the deployment and redeploy. Common causes include oversized Docker images (keep under 1 GB) and slow health checks.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Kubernetes Deployment" icon="dharmachakra" href="/self-host/deploy/kubernetes">
    Self-host on any Kubernetes cluster with Helm.
  </Card>

  <Card title="Operations" icon="gauge" href="/self-host/architecture/operations">
    Set up monitoring, metrics, and alerting.
  </Card>
</CardGroup>
