Amazon Redshift answers a different question than the databases in the rest of this cookbook. DynamoDB and RDS are built to serve one row fast, thousands of times a second. Redshift is built to read a billion rows and return one number.
That difference - between transactional and analytical workloads - shapes everything about how you use Redshift from an SDK. This page builds the mental model so the provisioning, loading, and query pages that follow read as applications of one idea.
Redshift is a columnar, massively-parallel (MPP) data warehouse for analytics (OLAP): large scans, aggregations, and joins over historical data, not high-frequency single-row reads and writes.
Insight: it stores each column separately, so a query that touches three columns of a hundred-column table reads only those three - the opposite of a row store, which reads the whole row.
Key Concepts:columnar storage, MPP / slices, distribution key, sort key, COPY bulk load, Redshift Spectrum, provisioned vs serverless.
When to Use: dashboards, reporting, BI, and ad-hoc analytics over gigabytes to petabytes; joining large fact and dimension tables; querying a data lake in place.
Limitations/Trade-offs: high per-query throughput at the cost of per-row latency and write amplification - single-row inserts are an anti-pattern; you load in bulk instead.
Related Topics: provisioned clusters vs serverless, the Redshift Data API, COPY from S3, and cross-region snapshots.
Start with the word that does the most work: columnar.
A transactional database like PostgreSQL stores a table row by row. All of a customer's fields sit together on disk, so fetching one customer by id reads one contiguous block. That is perfect for OLTP - online transaction processing - where each request touches a few rows by key.
Analytics asks the opposite. "What was total revenue by region last quarter?" touches millions of rows but only three or four columns. In a row store, the engine still reads every column of every row just to reach the ones it needs. Redshift stores each column in its own set of blocks, so that query reads only the region, amount, and order_date columns and skips the rest. Because a single column holds values of one type, Redshift also compresses it aggressively - often five to ten times - which shrinks the bytes scanned again.
The second pillar is MPP - massively parallel processing. A Redshift warehouse is not one machine. A provisioned cluster is a leader node plus one or more compute nodes, and each compute node is divided into slices. Your table's rows are spread across every slice according to its distribution key. When you run a query, the leader node compiles a plan, ships it to all slices, and each slice scans its own portion at the same time. Ten slices scanning in parallel finish a full-table aggregate roughly ten times faster than one.
So the model in one sentence: store columns separately, spread them across many slices, and let all the slices work at once.
This model changes how you talk to Redshift from an SDK.
With DynamoDB you call PutItem and GetItem per record. With Redshift you almost never insert one row at a time - a single-row INSERT writes to every relevant column block and wastes the columnar layout. Instead you bulk load with the COPY command, which reads many files from S3 in parallel, one file stream per slice, and lands millions of rows in one statement. Loading is a batch operation by design.
Querying is SQL, and you send that SQL one of two ways. Traditionally a client opens a JDBC or psql connection to the cluster endpoint and streams results - useful for a BI tool, but awkward from serverless code that has no long-lived connection. The SDK-native path is the Redshift Data API: you submit a statement, get back an id, poll until it finishes, and fetch the results, with no connection to manage. That is why the rest of this section leans on the Data API.
Two design choices govern performance, and both are SQL-level, not SDK-level:
The distribution key decides which slice each row lands on. Choosing the column you join on most often means matching rows sit on the same slice, so a join happens locally instead of shuffling data across the network. DISTSTYLE ALL copies a small dimension table to every slice; EVEN and AUTO spread rows without a join hint.
The sort key decides the order of rows within each slice. Sorting by a date column lets Redshift skip whole blocks whose value range cannot match a WHERE order_date > '2026-01-01' - the equivalent of an index for range scans.
The SDK's job is the surrounding lifecycle. The control-plane clients (@aws-sdk/client-redshift for provisioned, @aws-sdk/client-redshift-serverless for serverless) create and resize the warehouse, attach IAM roles, and take snapshots. The @aws-sdk/client-redshift-data client runs the SQL. You rarely touch the data-plane connection yourself.
Here is the shape of the whole interaction - submit analytic SQL and read the result - without any JDBC connection.
# --- Python (boto3) ---import boto3data = boto3.client("redshift-data", region_name="us-east-1")# Analytics is one aggregate over many rows - sent as SQL, run in parallel by the cluster.resp = data.execute_statement( WorkgroupName="analytics-wg", # serverless target Database="dev", Sql="SELECT region, SUM(amount) FROM sales GROUP BY region",)print("statement id:", resp["Id"]) # async - poll DescribeStatement next
// --- TypeScript (AWS SDK v3) ---import { RedshiftDataClient, ExecuteStatementCommand } from "@aws-sdk/client-redshift-data";const data = new RedshiftDataClient({ region: "us-east-1" });// Analytics is one aggregate over many rows - sent as SQL, run in parallel by the cluster.const resp = await data.send(new ExecuteStatementCommand({ WorkgroupName: "analytics-wg", // serverless target Database: "dev", Sql: "SELECT region, SUM(amount) FROM sales GROUP BY region",}));console.log("statement id:", resp.Id); // async - poll DescribeStatement next
The call returns immediately with an id because the query runs on the warehouse, not in your process. That asynchronous, connectionless pattern is the heart of the Data API page.
The first is Redshift Spectrum. You do not have to load data into the warehouse to query it. With an external schema over an AWS Glue Data Catalog, Redshift can run SQL directly against files sitting in S3 - Parquet, ORC, CSV - joining that data lake against tables already in the cluster. Loaded tables give the fastest queries; Spectrum trades some speed for querying cold or huge data in place without a COPY. Both are just SQL you send through the Data API.
The second is the provisioned-versus-serverless split, which is really a question of who manages the slices. A provisioned cluster is a fixed set of nodes you size, pay for around the clock, and resize deliberately - predictable and cost-effective for steady heavy load. Redshift Serverless hides the nodes entirely: you set a base capacity in RPUs (Redshift Processing Units), and it scales compute to the query, billing per second of use and nothing when idle. The columnar MPP engine underneath is identical; only the capacity model and the SDK client differ.
The trade-off to internalize is the mirror image of DynamoDB's. DynamoDB gives flat latency for keyed reads and punishes full-table scans. Redshift gives enormous scan and aggregation throughput and punishes high-frequency single-row access. Point a transactional workload at Redshift and you will fight write amplification and connection limits; point analytics at an OLTP database and you will melt it with full scans. Choosing Redshift is choosing the OLAP side of that line.
The habit to carry forward: think in bulk and in columns. Load many rows at once, query wide aggregates over few columns, pick distribution and sort keys from your biggest joins and filters, and reach for the Data API rather than a raw connection whenever your code is short-lived.
"Redshift is just a bigger PostgreSQL." - It speaks PostgreSQL-flavored SQL, but it is columnar and MPP under the hood. Row-at-a-time inserts and lookups that suit Postgres are anti-patterns here.
"I should INSERT rows as they arrive." - Single-row inserts waste the columnar layout and are slow at volume. Batch into S3 and load with COPY, or stream through a staging table.
"A distribution key is like a primary key." - It only decides which slice a row lives on, to make joins local. It is a performance placement choice, not a uniqueness constraint.
"Spectrum is a separate service I query differently." - Spectrum is the same Redshift SQL engine reading S3 through an external schema. You send the query the same way; only the table's storage differs.
"Serverless and provisioned are different engines." - The columnar MPP core is identical. They differ in how capacity is sized and billed and in which SDK client provisions them.
Analytics (OLAP): large scans, aggregations, and joins over historical data for dashboards, reporting, and BI. It is not built for high-frequency single-row reads and writes, which belong in RDS, Aurora, or DynamoDB.
Why is columnar storage faster for analytics?
A query that touches a few columns reads only those columns' blocks instead of every column of every row. Storing one data type per column also compresses well, so Redshift scans far fewer bytes than a row store would for the same aggregate.
What does "massively parallel" mean here?
A cluster splits each table across many slices (units of compute). When you run a query, every slice scans its own portion at the same time, so throughput scales with the number of slices rather than being limited to one machine.
How is Redshift different from RDS or Aurora?
RDS and Aurora are row-oriented transactional databases optimized for many small keyed operations. Redshift is column-oriented and MPP, optimized for few large analytical queries. You often keep both: OLTP data in RDS and a copy loaded into Redshift for analytics.
Why load with COPY instead of INSERT?
COPY reads many files from S3 in parallel, one stream per slice, landing millions of rows efficiently in one statement. Single-row INSERTs write to every column block individually and are far slower at scale, so bulk loading is the intended path.
What are distribution and sort keys?
The distribution key decides which slice each row lands on, so choosing a common join column keeps matching rows together and avoids network shuffles. The sort key orders rows within a slice, letting Redshift skip blocks that cannot match a range filter.
Do I need a JDBC connection to query Redshift?
Not from the SDK. The Redshift Data API lets you submit SQL, receive a statement id, poll for completion, and fetch results with no persistent connection - ideal for Lambda and other short-lived code. JDBC or psql still suits BI tools and interactive sessions.
What is Redshift Spectrum?
Spectrum lets Redshift query data left in S3 through an external schema over a Glue Data Catalog, without loading it into the warehouse first. It runs the same SQL engine, so you can join S3 files against loaded tables in one query, trading some speed for querying data in place.