Most Redshift teams have now wired up a database zero-ETL integration — Aurora or RDS MySQL replicating into the warehouse with no pipeline to babysit. The business data that people actually ask for, though, usually does not live in Aurora. It lives in Salesforce, SAP, ServiceNow, Zendesk, Facebook Ads and a dozen other SaaS applications, and it has historically arrived in Redshift via a third-party connector, a paid ELT tool, or a Lambda that somebody wrote against a REST API in 2021 and no longer understands.
Zero-ETL integrations for applications close that gap. AWS Glue exposes a managed integration that pulls objects from a SaaS source on a schedule and lands them in an Amazon Redshift (or SageMaker Lakehouse) target, handling the API paging, the incremental change capture and the schema mapping for you. There is no Glue job to write, no connector cluster to size, and no bespoke checkpoint table.
This tutorial walks through setting one up against Salesforce, then covers the parts that are not in the console wizard: how the initial and incremental loads actually behave, what a soft-deleted record does to your models, and how to model the landed tables so they are usable downstream.
What you need before you start
- A Redshift target — Serverless workgroup or RA3 provisioned cluster. If you are still deciding, we work through the tradeoff in RA3 vs Serverless in 2026.
- A target database and schema in Redshift that the integration will own. Give it its own schema, e.g.
raw_salesforce. Do not point it at a schema humans also write to. - An IAM role Glue can assume, with permissions on the Redshift target and on the connection secret.
- A connection to the SaaS source, created in AWS Glue, holding the OAuth credentials in Secrets Manager.
The credential you use for the source matters more than it looks. The integration can only see objects and fields the connected user can see, so a Salesforce integration user with a restrictive profile silently produces tables that are missing columns. Provision a dedicated integration user with read access to every object you intend to replicate, and document it — this is the single most common cause of "the field exists in Salesforce but not in Redshift".
Step 1: create the source connection
In AWS Glue, create a connection of the appropriate type (Salesforce, ServiceNow, Zendesk, SAP OData, and so on). Glue drives an OAuth flow and stores the resulting tokens in Secrets Manager. Two things to check:
- Sandbox vs production instance. Salesforce sandboxes authenticate against a different host. Pointing a production integration at a sandbox is an afternoon you do not get back.
- Token refresh. The stored refresh token is what keeps the integration alive. If your identity team rotates or revokes it, the integration fails on its next run with an authentication error and stays failed. Put that secret on the same rotation calendar as the rest of the warehouse credentials.
Step 2: authorize the Redshift target
The Redshift side needs to accept the integration. On the target namespace or cluster, enable case sensitivity, which zero-ETL integrations require:
-- Serverless: set on the workgroup; provisioned: on the parameter group
-- enable_case_sensitive_identifier = true
SHOW enable_case_sensitive_identifier;
Then create an authorization allowing the integration principal to write into the target, and create the destination database from the integration once it exists:
CREATE DATABASE salesforce_raw FROM INTEGRATION '<integration-id>';
Until that CREATE DATABASE ... FROM INTEGRATION runs, the integration will show as active on the Glue side while nothing lands in Redshift. It is the step people miss.
Step 3: define the integration and pick objects
Create the zero-ETL integration in Glue, choosing the source connection, the target Redshift namespace, and the list of source objects. Start narrow. For a Salesforce CRM analytics use case, that is usually:
Account, Contact, Lead, Opportunity, OpportunityLineItem,
User, Campaign, CampaignMember
Resist the temptation to select every object. Each one is an ongoing API cost against your SaaS tenant's rate limits, and the audit and metadata objects are large, noisy and almost never modelled.
Set the refresh interval next. Intervals are configurable down to roughly a quarter of an hour; hourly is a sane default for CRM data. Sub-hourly refreshes on a large object burn API quota for reporting that nobody reads before 9am. If a stakeholder insists on near-real-time, ask which decision changes between 09:00 and 09:15 — usually the honest answer is none.
Step 4: watch the initial load
The first run is a full historical extract of every selected object, and it is by far the heaviest. Expect it to take from minutes to many hours depending on object size and the source tenant's API throughput. During this window:
- Do not point production dashboards at the schema. Tables are populated progressively.
- Watch for objects stuck in a failed state. A single object failing does not stop the others, so a partially healthy integration looks green at a glance.
Once seeded, subsequent runs are incremental: the integration tracks changes on the source and applies inserts, updates and deletes to the Redshift tables. You do not write MERGE statements for this data. If you do need that pattern elsewhere in the warehouse, our MERGE, upserts and SCD Type 2 guide covers it.
Step 5: verify, then model on top
Check what arrived before anyone builds on it:
SELECT "table", tbl_rows
FROM svv_table_info
WHERE schema = 'salesforce'
ORDER BY tbl_rows DESC;
And confirm freshness per object with whatever the source's own modified timestamp is:
SELECT MAX("LastModifiedDate") AS newest_change,
DATEDIFF(minute, MAX("LastModifiedDate"), GETDATE()) AS lag_minutes
FROM salesforce_raw.salesforce."Opportunity";
Note the double quotes. With case-sensitive identifiers on, Opportunity and opportunity are different names, and unquoted SQL will fail with a relation-not-found error that reads like the table is missing. This surprises every team once. Bake the quoting convention into your dbt sources or views on day one — see Running dbt on Amazon Redshift for how we structure that layer.
Three modelling rules for the landed data:
- Treat the integration schema as read-only. Never
UPDATE, never add columns, never build indexes of your own logic into it. The integration owns those tables and can resync them. - Build a curated layer of views or models over it. Rename
Opportunity.StageNameto something a finance analyst recognises once, in one place. - Handle soft deletes explicitly. Salesforce records moved to the recycle bin, and objects excluded from a later object list, do not always disappear the way a naive
SELECT *assumes. Decide per object whether deleted rows are filtered or retained as history, and write it down.
Failure modes worth monitoring
- Source schema drift. A new custom field appears in Salesforce and flows through; a field is deleted and downstream models break. Alert on unexpected column changes in
svv_columns. - API quota exhaustion. The integration competes with every other consumer of the same SaaS tenant. If marketing installs a new tool that hammers the API, your refreshes start failing.
- Silent per-object failure. Emit a CloudWatch alarm on integration state rather than trusting a console glance.
- Cost attribution. Ingest consumes Redshift compute on the target. If you run a mixed workload, keep an eye on it as part of your regular review — the 2026 Redshift cost-tuning checklist has the query patterns for that.
When not to use it
Zero-ETL for applications is the right answer when you want a faithful replica of SaaS objects in the warehouse with minimal operational surface. It is the wrong answer when you need transformation in flight, when the source is not a supported connector, or when you need sub-minute latency — that is streaming territory, covered in streaming ingestion from Kinesis. And if your source is an operational database rather than a SaaS app, use the database integration instead: setting up Aurora to Redshift zero-ETL.
Replacing brittle SaaS connectors with managed integrations — and building the curated layer that makes the landed data usable — is core Data Integration & Migration work for us, and it usually runs alongside Zero-ETL & Real-Time Ingestion design for the rest of the warehouse. If you are paying a per-row ELT bill for Salesforce data that Redshift could ingest natively, get in touch and we will scope the swap.