# Amazon Redshift Destination Config Reference

<p><a href="https://www.rudderstack.com/docs/destinations/warehouse-destinations/redshift/" >Amazon Redshift</a> is a warehouse destination. RudderStack stages events as files in S3, then loads them into a Redshift cluster or Serverless workgroup on a schedule.</p>
<p>In an Amazon Redshift destination spec:</p>
<ul>
<li><code>type: rs</code></li>
<li><code>definition_version: 1</code></li>
</ul>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="sample-configuration">Sample configuration</h2><div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">version: rudder/v1
kind: destination
metadata:
  name: redshift-prod
spec:
  id: redshift-prod
  display_name: Redshift Production
  type: rs
  definition_version: 1
  enabled: true
  config:
    database: analytics
    user: &#34;{{ .REDSHIFT_USER }}&#34;
    namespace: rudder_events

    use_iam_for_auth: true
    iam_role_arn_for_auth: &#34;arn:aws:iam::123456789012:role/RudderStackRedshift&#34;
    cluster_region: us-east-1
    use_serverless: false
    cluster_id: analytics-cluster

    use_ssh: false

    use_rudder_storage: false
    bucket_name: acme-redshift-staging
    prefix: rudder
    role_based_auth: true
    iam_role_arn: &#34;arn:aws:iam::123456789012:role/RudderStackS3&#34;
    enable_sse: false
    cleanup_object_storage_files: false

    sync_frequency: &#34;180&#34;
    sync_start_at: &#34;01:00&#34;
    exclude_window:
      start_time: &#34;02:00&#34;
      end_time: &#34;03:00&#34;

    prefer_append: true
    skip_users_table: true
    skip_tracks_table: false
    json_paths: context.traits,properties.metadata

    underscore_divide_numbers: false
    allow_users_context_traits: false

    connection_mode:
      web: cloud
      cloud: cloud
    consent_management:
      web:
        - provider: oneTrust
          consents:
            - analytics</code></pre></div>
</div>
<p>The above example connects to a provisioned cluster with IAM authentication and stages files in your own bucket through an IAM role, so it carries no password or access keys. Which keys apply depends on three switches — see <a href="#key-dependencies" >Key dependencies</a>.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="config-keys">Config keys</h2><p><code>config</code> accepts only the keys listed below. The <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/destination-types/#config-key-rules" >shared config key rules</a> cover unknown keys, defaults, and immutability.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="key-dependencies">Key dependencies</h3><p><code>use_iam_for_auth</code>, <code>use_serverless</code>, <code>use_rudder_storage</code>, <code>role_based_auth</code>, and <code>use_ssh</code> decide which other keys apply. Rudder CLI enforces the requirements marked <strong>Enforced</strong>; the rest are accepted whatever the switch says, so a key that doesn&rsquo;t apply is stored and ignored.</p>
<table>
<thead>
<tr>
<th>Key</th>
<th>Applies when</th>
<th>Required then</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>host</code>, <code>port</code>, <code>password</code></td>
<td><code>use_iam_for_auth</code> is <code>false</code></td>
<td>Enforced</td>
</tr>
<tr>
<td><code>iam_role_arn_for_auth</code>, <code>cluster_region</code></td>
<td><code>use_iam_for_auth</code> is <code>true</code></td>
<td>Enforced</td>
</tr>
<tr>
<td><code>cluster_id</code></td>
<td><code>use_iam_for_auth</code> is <code>true</code> and <code>use_serverless</code> is <code>false</code></td>
<td>Enforced</td>
</tr>
<tr>
<td><code>workgroup_name</code></td>
<td><code>use_iam_for_auth</code> is <code>true</code> and <code>use_serverless</code> is <code>true</code></td>
<td>Enforced</td>
</tr>
<tr>
<td><code>ssh</code></td>
<td><code>use_ssh</code> is <code>true</code></td>
<td>Enforced, all four fields</td>
</tr>
<tr>
<td><code>bucket_name</code></td>
<td><code>use_rudder_storage</code> is <code>false</code></td>
<td>Enforced</td>
</tr>
<tr>
<td><code>iam_role_arn</code></td>
<td><code>use_rudder_storage</code> is <code>false</code> and <code>role_based_auth</code> is <code>true</code>, which is the default</td>
<td>Enforced</td>
</tr>
<tr>
<td><code>prefix</code>, <code>role_based_auth</code>, <code>enable_sse</code>, <code>cleanup_object_storage_files</code></td>
<td><code>use_rudder_storage</code> is <code>false</code></td>
<td>No</td>
</tr>
<tr>
<td><code>access_key_id</code>, <code>access_key</code></td>
<td><code>use_rudder_storage</code> is <code>false</code> and <code>role_based_auth</code> is <code>false</code></td>
<td>No</td>
</tr>
</tbody>
</table>

<blockquote class="warning">
  <div class="tip-quote">
    
    <div class="tip-text"><p><code>validate</code> fills in defaults before it checks the spec, so an omitted key is checked as though you had written its default. Two keys are worth knowing about:</p>
<ul>
<li>Omitting <code>use_serverless</code> selects a provisioned cluster, which makes <code>cluster_id</code> required.</li>
<li>With your own storage, omitting <code>role_based_auth</code> selects role-based authentication, which makes <code>iam_role_arn</code> required.</li>
</ul>
</div>
  </div>
</blockquote>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="connection">Connection</h3><div class="rs-ckeys">
<div class="rs-ckey" id="database">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">database</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Name of the Redshift database RudderStack loads data into.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>At most 100 characters, and must not contain line breaks.</li>
<li>A <code>{{ path || fallback }}</code> template is accepted in place of a literal.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="user">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">user</p>RequiredSecret</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Database user with read and write access to <code>database</code>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>At most 100 characters, and must not contain line breaks.</li>
<li>A <code>{{ path || fallback }}</code> template is accepted in place of a literal.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  See <a href="https://www.rudderstack.com/docs/destinations/warehouse-destinations/redshift/#setting-user-permissions-in-redshift" >Setting user permissions in Redshift</a>.
</div>

</div>

<div class="rs-ckey" id="namespace">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">namespace</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Schema RudderStack creates its tables in. Defaults to the source name when omitted.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>At most 64 characters, and must not start with <code>pg_</code> in any capitalization.</li>
<li>A <code>{{ path || fallback }}</code> template is accepted in place of a literal.</li>
<li>The Redshift setup guide says the namespace can&rsquo;t be changed later, so treat it as fixed. Unlike BigQuery&rsquo;s, it isn&rsquo;t marked immutable in the API schema, so a change isn&rsquo;t rejected.</li>
</ul>

</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="authentication">Authentication</h3><p><code>use_iam_for_auth</code> selects between a database password and the RudderStack IAM role. With IAM, <code>use_serverless</code> then selects between a provisioned cluster and a Serverless workgroup.</p>
<div class="rs-ckeys">
<div class="rs-ckey" id="use_iam_for_auth">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">use_iam_for_auth</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Authenticate with the RudderStack IAM role instead of a database password.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>The dashboard defaults this field to <code>false</code>. Rudder CLI requires it explicitly.</li>
<li>A spec that omits this key fails validation.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  See <a href="https://www.rudderstack.com/docs/destinations/aws-iam-role-for-rudderstack/redshift-iam-role/" >Redshift IAM role</a> for how to create the role.
</div>

</div>

<div class="rs-ckey" id="host">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">host</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Hostname of the Redshift cluster endpoint.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Required when <code>use_iam_for_auth</code> is <code>false</code>. Leave it unset otherwise.</li>
<li>1 to 255 characters, and must not contain line breaks. An <code>ngrok.io</code> host is rejected.</li>
<li>A <code>{{ path || fallback }}</code> template is accepted in place of a literal.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="port">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">port</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Port of the Redshift cluster endpoint, written as a string — <code>&quot;5439&quot;</code>, not <code>5439</code>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Required when <code>use_iam_for_auth</code> is <code>false</code>. Leave it unset otherwise.</li>
<li>At most 100 characters, and must not contain line breaks.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="password">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">password</p>RequiredSecret</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Password for <code>user</code>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Required when <code>use_iam_for_auth</code> is <code>false</code>. Leave it unset otherwise.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  Supply it as a <code>{{ .VAR }}</code> reference rather than a literal — see <a href="#secrets" >Secrets</a>.
</div>

</div>

<div class="rs-ckey" id="iam_role_arn_for_auth">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">iam_role_arn_for_auth</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  ARN of the RudderStack IAM role used to obtain database credentials.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Required when <code>use_iam_for_auth</code> is <code>true</code>. Leave it unset otherwise.</li>
<li>At most 100 characters, and must not contain line breaks.</li>
<li>A <code>{{ path || fallback }}</code> template is accepted in place of a literal.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="cluster_region">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">cluster_region</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  AWS region of the cluster or workgroup — for example <code>us-east-1</code>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Required when <code>use_iam_for_auth</code> is <code>true</code>. Leave it unset otherwise.</li>
<li>1 to 255 characters, and must not contain line breaks.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="use_serverless">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">use_serverless</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p><p class="rs-ckey__field">
    Default value:
    <code>false</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Connect to a Redshift Serverless workgroup instead of a provisioned cluster.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Applies when <code>use_iam_for_auth</code> is <code>true</code>.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  See <a href="#key-dependencies" >Key dependencies</a> for what omitting it makes required.
</div>

</div>

<div class="rs-ckey" id="cluster_id">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">cluster_id</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Identifier of the provisioned Redshift cluster.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Required when <code>use_iam_for_auth</code> is <code>true</code> and <code>use_serverless</code> is <code>false</code>. Leave it unset otherwise.</li>
<li>1 to 255 characters, and must not contain line breaks.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="workgroup_name">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">workgroup_name</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Name of the <a href="https://docs.aws.amazon.com/redshift/latest/mgmt/serverless-console-workgroups.html" >Redshift Serverless workgroup</a>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Required when <code>use_iam_for_auth</code> is <code>true</code> and <code>use_serverless</code> is <code>true</code>. Leave it unset otherwise.</li>
<li>1 to 255 characters, and must not contain line breaks.</li>
</ul>

</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="ssh-tunnel">SSH tunnel</h3>
<html lang="en">
<blockquote class="info">
  <div class="tip-quote">
    
    <div class="tip-text">SSH tunneling is available on the Enterprise plan. See <a href="https://www.rudderstack.com/docs/destinations/warehouse-destinations/redshift/#ssh-connection-settings" >SSH connection settings</a>.</div>
  </div>
</blockquote>

</html>
<div class="rs-ckeys">
<div class="rs-ckey" id="use_ssh">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">use_ssh</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p><p class="rs-ckey__field">
    Default value:
    <code>false</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Connect to Redshift through an SSH tunnel via a bastion host.
</p>

</div>

<div class="rs-ckey" id="ssh">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">ssh</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>object</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Bastion host connection details.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Required when <code>use_ssh</code> is <code>true</code>, with all four fields. Leave it unset otherwise.</li>
<li><code>host</code> — IP address or hostname of the bastion host. At most 100 characters.</li>
<li><code>port</code> — SSH port of the bastion host, as a string. At most 100 characters.</li>
<li><code>user</code> — user RudderStack logs in to the bastion host as. <strong>Secret</strong> — see <a href="#secrets" >Secrets</a>.</li>
<li><code>public_key</code> — the public key RudderStack generates for this destination.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  <div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">use_ssh: true
ssh:
  host: 203.0.113.10
  port: &#34;22&#34;
  user: &#34;{{ .REDSHIFT_SSH_USER }}&#34;
  public_key: &#34;ssh-rsa AAAA...&#34;</code></pre></div>
</div>
<p>RudderStack holds the private key; add <code>public_key</code> to the bastion host&rsquo;s <code>authorized_keys</code>. The key comes from RudderStack, so the practical route is to enable SSH on the destination in the dashboard, then <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/import-resources/" >import</a> it to pick up the value.</p>

</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="object-storage">Object storage</h3><p><code>use_rudder_storage</code> decides whether RudderStack stages files in its own bucket or in yours. The keys below it apply only to your own bucket.</p>
<div class="rs-ckeys">
<div class="rs-ckey" id="use_rudder_storage">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">use_rudder_storage</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Stage files in RudderStack-managed object storage instead of your own S3 bucket.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Available only on RudderStack-hosted data planes. Self-hosted data planes must set <code>false</code> and configure a bucket.</li>
<li>The dashboard defaults this field to <code>false</code>. Rudder CLI requires it explicitly.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="bucket_name">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">bucket_name</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Name of the staging S3 bucket. The bucket must already exist.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Required when <code>use_rudder_storage</code> is <code>false</code>. Leave it unset otherwise.</li>
<li>3 to 63 characters: lowercase letters, digits, dots, and hyphens, starting and ending with a letter or digit. Must not start with <code>xn--</code>, contain consecutive dots, or look like an IPv4 address.</li>
<li>A <code>{{ path || fallback }}</code> template is accepted in place of a literal.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="prefix">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">prefix</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Folder prefix inside the staging bucket, at <code>s3://&lt;bucket_name&gt;/&lt;prefix&gt;/</code>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Applies when <code>use_rudder_storage</code> is <code>false</code>. Leave it unset otherwise.</li>
<li>At most 100 characters, with no whitespace.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="role_based_auth">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">role_based_auth</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p><p class="rs-ckey__field">
    Default value:
    <code>true</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Access the staging bucket with an IAM role (<code>iam_role_arn</code>) rather than an access key pair.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Applies when <code>use_rudder_storage</code> is <code>false</code>. Leave it unset otherwise.</li>
<li>Defaults to <code>true</code>, so <code>iam_role_arn</code> is required unless you set this to <code>false</code> and supply access keys.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="iam_role_arn">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">iam_role_arn</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  ARN of the IAM role RudderStack assumes to read and write the staging bucket.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Required when <code>use_rudder_storage</code> is <code>false</code> and <code>role_based_auth</code> is <code>true</code>. Leave it unset otherwise.</li>
<li>At most 100 characters, and must not contain line breaks.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  See <a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/amazon-s3/#s3-permissions-for-warehouse-destinations" >S3 permissions for warehouse destinations</a>.
</div>

</div>

<div class="rs-ckey" id="access_key_id">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">access_key_id</p>Secret</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  AWS access key ID for the staging bucket.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Applies when <code>use_rudder_storage</code> is <code>false</code> and <code>role_based_auth</code> is <code>false</code>. Leave it unset otherwise.</li>
<li>Not required even then — neither Rudder CLI nor the API asks for it.</li>
<li>At most 100 characters, and must not contain line breaks.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="access_key">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">access_key</p>Secret</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  AWS secret access key matching <code>access_key_id</code>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Applies on the same terms as <code>access_key_id</code>, and is likewise not required.</li>
<li>At most 100 characters, and must not contain line breaks.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  <blockquote class="warning">
  <div class="tip-quote">
    
    <div class="tip-text">Access key authentication is deprecated. Use <code>role_based_auth: true</code> with <code>iam_role_arn</code>.</div>
  </div>
</blockquote>

</div>

</div>

<div class="rs-ckey" id="enable_sse">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">enable_sse</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p><p class="rs-ckey__field">
    Default value:
    <code>false</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Enable server-side encryption on the staging bucket.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Applies when <code>use_rudder_storage</code> is <code>false</code>.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="cleanup_object_storage_files">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">cleanup_object_storage_files</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p><p class="rs-ckey__field">
    Default value:
    <code>false</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Delete staged files from the bucket after a sync completes successfully.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Applies when <code>use_rudder_storage</code> is <code>false</code>.</li>
</ul>

</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="sync-scheduling">Sync scheduling</h3><div class="rs-ckeys">
<div class="rs-ckey" id="sync_frequency">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">sync_frequency</p>Required</div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  How often RudderStack syncs staged events into Redshift, in minutes. Written as a string, not a number.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>One of <code>5</code>, <code>10</code>, <code>15</code>, <code>30</code>, <code>60</code>, <code>180</code>, <code>360</code>, <code>720</code>, or <code>1440</code>.</li>
<li>The dashboard defaults this field to <code>180</code>. Rudder CLI requires it explicitly.</li>
<li>A spec that omits this key fails validation.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="sync_start_at">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">sync_start_at</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Time of day, in UTC, that anchors the sync schedule. Subsequent syncs are computed from it at <code>sync_frequency</code> intervals. Written as <code>HH:MM</code>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Not validated locally: any string is accepted, and a value the scheduler can&rsquo;t parse silently yields no scheduled times.</li>
</ul>

</div>

</div>

<div class="rs-ckey" id="exclude_window">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">exclude_window</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>object</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Daily window, in UTC, during which RudderStack doesn&rsquo;t sync. Omit the block entirely to sync around the clock.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>When present, both fields are required: <code>start_time</code> and <code>end_time</code>, each <code>HH:MM</code>.</li>
<li>Neither field&rsquo;s format is validated locally.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  <div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">exclude_window:
  start_time: &#34;02:00&#34;
  end_time: &#34;03:00&#34;</code></pre></div>
</div>

</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="table-behavior">Table behavior</h3><div class="rs-ckeys">
<div class="rs-ckey" id="prefer_append">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">prefer_append</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p><p class="rs-ckey__field">
    Default value:
    <code>true</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Append incoming events to existing tables. Set it to <code>false</code> to merge instead, which guarantees no duplicates at the cost of noticeably longer syncs. This is what the dashboard calls <strong>Warehouse Append</strong>.
</p>

<div class="rs-ckey__extra">
  Appending can let duplicates through — most often SDK retries, and especially against data older than 7 days.
</div>

</div>

<div class="rs-ckey" id="skip_users_table">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">skip_users_table</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p><p class="rs-ckey__field">
    Default value:
    <code>true</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Send <code>identify</code> events only to the <code>identifies</code> table, skipping the <code>users</code> table. The <code>users</code> table holds one row per unique user and is maintained with a merge, which can add significant time to each sync.
</p>

</div>

<div class="rs-ckey" id="skip_tracks_table">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">skip_tracks_table</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p><p class="rs-ckey__field">
    Default value:
    <code>false</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Skip sending events to the <code>tracks</code> table. Per-event tables are unaffected.
</p>

</div>

<div class="rs-ckey" id="json_paths">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">json_paths</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>string</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Comma-separated dot-notation paths whose values are stored as JSON columns instead of being flattened. Applies to every <code>track</code> event sent to this destination.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>Not validated locally.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  See <a href="https://www.rudderstack.com/docs/destinations/warehouse-destinations/json-column-support/" >JSON Column Support</a>.
</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="legacy-column-naming">Legacy column naming</h3><p>Both keys below preserve the column naming of destinations created before the behavior changed. Leave them at their defaults on a new destination. Neither can be changed once the destination exists — the API rejects the update.</p>
<div class="rs-ckeys">
<div class="rs-ckey" id="underscore_divide_numbers">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">underscore_divide_numbers</p>ImmutableInternal</div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p><p class="rs-ckey__field">
    Default value:
    <code>false</code>
  </p>
<p class="rs-ckey__field">
  Description:
  When <code>false</code>, numeric suffixes in column names are preserved: <code>v3</code> stays <code>v3</code> rather than being split into <code>v_3</code>.
</p>

</div>

<div class="rs-ckey" id="allow_users_context_traits">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">allow_users_context_traits</p>ImmutableInternal</div>
  <p class="rs-ckey__field">
    Type:
    <code>boolean</code>
  </p><p class="rs-ckey__field">
    Default value:
    <code>false</code>
  </p>
<p class="rs-ckey__field">
  Description:
  When <code>false</code>, <code>context.traits.*</code> fields aren&rsquo;t promoted to top-level traits and are stored only as <code>context_traits_*</code> columns.
</p>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="per-source-keys">Per-source keys</h3><p>Both keys are objects keyed by the local source type — the tokens listed under <a href="#source-types" >Source types</a>. A key naming a source type this destination doesn&rsquo;t support fails validation.</p>
<div class="rs-ckeys">
<div class="rs-ckey" id="connection_mode">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">connection_mode</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>object</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Maps each source type you connect to the mode its events reach Redshift in, using the modes in <a href="#source-types" >Source types</a>.
</p>

<div class="rs-ckey__notes">
  <p class="rs-ckey__field">Notes:</p>
  <ul>
<li>An entry is required for each source type you connect — see <a href="#connect-a-source" >Connect a source</a>.</li>
</ul>

</div>

<div class="rs-ckey__extra">
  <div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">connection_mode:
  web: cloud
  cloud: cloud</code></pre></div>
</div>

</div>

</div>

<div class="rs-ckey" id="consent_management">
  <div class="rs-ckey__title">
    <p class="rs-ckey__name">consent_management</p></div>
  <p class="rs-ckey__field">
    Type:
    <code>object</code>
  </p>
<p class="rs-ckey__field">
  Description:
  Consent provider configuration per source type. The entry shape, accepted providers, and the rules on <code>resolution_strategy</code> and <code>consents</code> are shared across all destination types — see <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/destination-types/#consent-management" >Consent management</a>.
</p>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="source-types">Source types</h2><p>Amazon Redshift accepts events from these source types in the mentioned connection modes:</p>
<table>
<thead>
<tr>
<th>Source type</th>
<th>Connection mode</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>android</code></td>
<td><code>cloud</code></td>
</tr>
<tr>
<td><code>android_kotlin</code></td>
<td><code>cloud</code></td>
</tr>
<tr>
<td><code>ios</code></td>
<td><code>cloud</code></td>
</tr>
<tr>
<td><code>ios_swift</code></td>
<td><code>cloud</code></td>
</tr>
<tr>
<td><code>web</code></td>
<td><code>cloud</code></td>
</tr>
<tr>
<td><code>unity</code></td>
<td><code>cloud</code></td>
</tr>
<tr>
<td><code>cloud</code></td>
<td><code>cloud</code></td>
</tr>
<tr>
<td><code>react_native</code></td>
<td><code>cloud</code></td>
</tr>
<tr>
<td><code>flutter</code></td>
<td><code>cloud</code></td>
</tr>
<tr>
<td><code>cordova</code></td>
<td><code>cloud</code></td>
</tr>
</tbody>
</table>
<p>Every source type is <code>cloud</code> only — events reach the warehouse from RudderStack&rsquo;s servers, never in device mode.</p>

<html lang="en">
<blockquote class="info">
  <div class="tip-quote">
    
    <div class="tip-text">The dashboard additionally offers Amazon Redshift to AMP, Shopify, and cloud app sources. Rudder CLI doesn&rsquo;t manage those connections, so <code>amp</code>, <code>shopify</code>, and <code>cloud_source</code> are invalid here.</div>
  </div>
</blockquote>

</html>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="connect-a-source">Connect a source</h2><p>An event stream connection to this destination is checked against two rules at <code>validate</code> time.</p>
<p><strong>The source&rsquo;s type must be supported.</strong> A source&rsquo;s type resolves to one of the tokens above before the check — a JavaScript source resolves to <code>web</code>, and webhook and server-side SDK sources resolve to <code>cloud</code>. An unsupported type reports:</p>
<div class="rs-code">
  <div class="rs-code__head"><button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-text" data-lang="text">destination &#39;redshift-prod&#39; (type &#39;rs&#39;) does not support source &#39;my-source&#39;:
source type &#39;amp&#39; is not among supported source types: android, android_kotlin, ...</code></pre></div>
</div>
<p><strong>The destination config must carry a <code>connection_mode</code> entry for that source type.</strong> This lives on the destination spec, not on the <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/yaml-connections/" >connection spec</a>. Without it:</p>
<div class="rs-code">
  <div class="rs-code__head"><button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-text" data-lang="text">destination &#39;redshift-prod&#39; config has no &#39;connection_mode&#39; entry for source type &#39;web&#39;</code></pre></div>
</div>
<p>Amazon Redshift needs no additional config keys to connect a source of any type.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="secrets">Secrets</h2><p>Rudder CLI treats five keys as secrets: <code>user</code>, <code>password</code>, <code>access_key_id</code>, <code>access_key</code>, and <code>ssh.user</code>. Write each one you use as a <code>{{ .VAR }}</code> reference and supply the value at apply time:</p>
<div class="rs-code">
  <div class="rs-code__head">yaml<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-yaml" data-lang="yaml">config:
  user: &#34;{{ .REDSHIFT_USER }}&#34;
  password: &#34;{{ .REDSHIFT_PASSWORD }}&#34;</code></pre></div>
</div>
<div class="rs-code">
  <div class="rs-code__head">bash<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash">export RUDDER_REDSHIFT_USER=&#34;rudder&#34;
export RUDDER_REDSHIFT_PASSWORD=&#34;...&#34;
rudder-cli apply

# or
rudder-cli apply --var-file secrets.vars.yaml</code></pre></div>
</div>
<p>Note that:</p>
<ul>
<li>The YAML that <code>rudder-cli import</code> writes may or may not include secret keys. Before you apply, make sure every secret key your configuration needs is present and populated through variable substitution.</li>
<li><code>iam_role_arn_for_auth</code> and <code>iam_role_arn</code> aren&rsquo;t secrets — an ARN identifies a role but grants nothing on its own.</li>
</ul>
<p>See <a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/variable-substitution/" >How to Use Variable Substitution in Rudder CLI</a>.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="see-more">See more</h2><ul>
<li><a href="https://www.rudderstack.com/docs/destinations/warehouse-destinations/redshift/" >Amazon Redshift Destination</a> for cluster setup, user permissions, and network access</li>
<li><a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/destination-types/" >Destination Type Reference for Rudder CLI</a> for the rules shared across destination types</li>
<li><a href="https://www.rudderstack.com/docs/dev-tools/rudder-cli/yaml-destinations/" >Destination YAML Reference</a> for the spec envelope</li>
</ul>

