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

# BYO Storage

> Keep session recordings in your own cloud storage bucket for full data residency control.

Milana can store session recording data in a storage bucket that you own and control, rather than in Milana-managed storage. This gives you full control over data residency, retention policies, and access.

## How data flows

Session data is sent from the user's browser to Milana's ingest service, where it is buffered temporarily in encrypted-at-rest storage. Once a session window closes, the raw events are written to your bucket and immediately deleted from Milana's database.

Milana then processes the data in your bucket through several stages — encoding, generating transcripts, and building indexes — and writes all results back to the same bucket. Once a session is completed, no session recording data persists on Milana-managed storage.

The Milana web interface loads session replays directly from your bucket in the browser (by dynamically generating pre-signed URLs). This requires your bucket to have a CORS policy allowlisting our app domain.

## What stays in your bucket

* Raw session replays
* Encoded session replays
* Session transcripts
* User journey transcripts

## What Milana stores

Milana stores the following end-user metadata and derived data:

* **Metadata:** session metadata, user metadata, events, product-specific configuration, etc.
* **Derived data:** issues, user intent, taxonomies, summary statistics, indexes, etc.

Separately, Milana stores operational data related to your team's usage of the platform (e.g. logs, query history and analysis reports).

All data is handled in accordance with SOC 2 guidelines. We are **SOC 2 Type II certified**, with controls monitored by Vanta. See our [trust center](https://trust.getmilana.ai).

## Google Cloud Storage

### Create a bucket

Create a GCS bucket with the following settings. `us-east4` is strongly recommended for lowest latency.

| Setting                      | Value                  |
| ---------------------------- | ---------------------- |
| **Storage class**            | Standard               |
| **Autoclass**                | Enabled                |
| **Public access prevention** | Enforced               |
| **Access control**           | Uniform (bucket-level) |
| **Force destroy**            | Disabled               |

<Tabs>
  <Tab title="Terraform">
    ```hcl theme={null}
    resource "google_storage_bucket" "milana_data" {
      name                        = "your-company-milana-data"
      location                    = "US-EAST4"
      storage_class               = "STANDARD"
      uniform_bucket_level_access = true
      public_access_prevention    = "enforced"
      force_destroy               = false

      autoclass {
        enabled = true
      }

      cors {
        origin          = ["https://app.getmilana.ai"]
        method          = ["GET", "HEAD"]
        response_header = ["Content-Type"]
        max_age_seconds = 3600
      }
    }
    ```
  </Tab>

  <Tab title="CLI">
    See [Create buckets](https://cloud.google.com/storage/docs/creating-buckets#command-line) in the Google Cloud documentation.
  </Tab>
</Tabs>

### Grant Milana access

Grant the following Milana service accounts access to your bucket:

1. **Storage Object User** — allows Milana to read and write session data.
2. **Storage Object Viewer** — allows Milana's AI to read videos directly for transcription and analysis.

<Tabs>
  <Tab title="Terraform">
    ```hcl theme={null}
    resource "google_storage_bucket_iam_member" "milana_access" {
      bucket = google_storage_bucket.milana_data.name
      role   = "roles/storage.objectUser"
      member = "serviceAccount:milana-storage-accessor@vantara-prod.iam.gserviceaccount.com"
    }

    resource "google_storage_bucket_iam_member" "milana_vertex_access" {
      bucket = google_storage_bucket.milana_data.name
      role   = "roles/storage.objectViewer"
      member = "serviceAccount:service-183693770837@gcp-sa-aiplatform.iam.gserviceaccount.com"
    }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    gcloud storage buckets add-iam-policy-binding gs://your-company-milana-data \
      --member="serviceAccount:milana-storage-accessor@vantara-prod.iam.gserviceaccount.com" \
      --role="roles/storage.objectUser"

    gcloud storage buckets add-iam-policy-binding gs://your-company-milana-data \
      --member="serviceAccount:service-183693770837@gcp-sa-aiplatform.iam.gserviceaccount.com" \
      --role="roles/storage.objectViewer"
    ```
  </Tab>
</Tabs>

### Configure CORS for replay access

Milana's session replay player loads replay event data in the Milana web app using short-lived browser access. For Google Cloud Storage, that requires a bucket CORS policy that allows `https://app.getmilana.ai`.

Without this CORS policy, session replay can fail to load in the browser.

<Note>If you used the Terraform configuration above, CORS is already included in the bucket resource.</Note>

<Tabs>
  <Tab title="Terraform">
    Include the following `cors` block in your bucket resource:

    ```hcl theme={null}
    cors {
      origin          = ["https://app.getmilana.ai"]
      method          = ["GET", "HEAD"]
      response_header = ["Content-Type"]
      max_age_seconds = 3600
    }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    tmpfile="$(mktemp)"
    cat > "$tmpfile" <<'EOF'
    [
      {
        "origin": ["https://app.getmilana.ai"],
        "method": ["GET", "HEAD"],
        "responseHeader": ["Content-Type"],
        "maxAgeSeconds": 3600
      }
    ]
    EOF
    gcloud storage buckets update gs://your-company-milana-data --cors-file="$tmpfile"
    rm "$tmpfile"
    ```
  </Tab>
</Tabs>

## Amazon S3

### Create a bucket

Create an S3 bucket with the following settings. `us-east-1` is strongly recommended for lowest latency.

| Setting                     | Value                         |
| --------------------------- | ----------------------------- |
| **Region**                  | `us-east-1` (recommended)     |
| **Block all public access** | Enabled                       |
| **Bucket Versioning**       | Disabled (or per your policy) |
| **Default encryption**      | SSE-S3 or SSE-KMS             |

<Tabs>
  <Tab title="Terraform">
    ```hcl theme={null}
    resource "aws_s3_bucket" "milana_data" {
      bucket = "your-company-milana-data"
    }

    resource "aws_s3_bucket_public_access_block" "milana_data" {
      bucket = aws_s3_bucket.milana_data.id

      block_public_acls       = true
      block_public_policy     = true
      ignore_public_acls      = true
      restrict_public_buckets = true
    }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    aws s3api create-bucket \
      --bucket your-company-milana-data \
      --region us-east-1

    aws s3api put-public-access-block \
      --bucket your-company-milana-data \
      --public-access-block-configuration \
        BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
    ```
  </Tab>
</Tabs>

### Grant Milana access

Add a bucket policy that grants Milana's service account read and write access. Replace `your-company-milana-data` with your bucket name.

<Tabs>
  <Tab title="Terraform">
    ```hcl theme={null}
    resource "aws_s3_bucket_policy" "milana_access" {
      bucket = aws_s3_bucket.milana_data.id

      policy = jsonencode({
        Version = "2012-10-17"
        Statement = [
          {
            Sid       = "MilanaAccess"
            Effect    = "Allow"
            Principal = {
              AWS = "arn:aws:iam::969209892974:user/milana-storage-accessor"
            }
            Action = [
              "s3:GetObject",
              "s3:PutObject",
              "s3:DeleteObject",
              "s3:ListBucket",
            ]
            Resource = [
              aws_s3_bucket.milana_data.arn,
              "${aws_s3_bucket.milana_data.arn}/*",
            ]
          }
        ]
      })
    }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    cat > /tmp/milana-bucket-policy.json <<'EOF'
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "MilanaAccess",
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::969209892974:user/milana-storage-accessor"
          },
          "Action": [
            "s3:GetObject",
            "s3:PutObject",
            "s3:DeleteObject",
            "s3:ListBucket"
          ],
          "Resource": [
            "arn:aws:s3:::your-company-milana-data",
            "arn:aws:s3:::your-company-milana-data/*"
          ]
        }
      ]
    }
    EOF
    aws s3api put-bucket-policy \
      --bucket your-company-milana-data \
      --policy file:///tmp/milana-bucket-policy.json
    rm /tmp/milana-bucket-policy.json
    ```
  </Tab>
</Tabs>

### Configure CORS for replay access

Milana's session replay player loads replay event data in the browser. For S3, that requires a CORS configuration that allows `https://app.getmilana.ai`.

<Tabs>
  <Tab title="Terraform">
    ```hcl theme={null}
    resource "aws_s3_bucket_cors_configuration" "milana_data" {
      bucket = aws_s3_bucket.milana_data.id

      cors_rule {
        allowed_origins = ["https://app.getmilana.ai"]
        allowed_methods = ["GET", "HEAD"]
        allowed_headers = ["*"]
        max_age_seconds = 3600
      }
    }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    cat > /tmp/milana-cors.json <<'EOF'
    {
      "CORSRules": [
        {
          "AllowedOrigins": ["https://app.getmilana.ai"],
          "AllowedMethods": ["GET", "HEAD"],
          "AllowedHeaders": ["*"],
          "MaxAgeSeconds": 3600
        }
      ]
    }
    EOF
    aws s3api put-bucket-cors \
      --bucket your-company-milana-data \
      --cors-configuration file:///tmp/milana-cors.json
    rm /tmp/milana-cors.json
    ```
  </Tab>
</Tabs>

## Need help?

Contact [help@getmilana.ai](mailto:help@getmilana.ai) or your onboarding specialist to complete your BYO storage setup.
