Batch Ingestion Patterns: DMS, AppFlow, DataSync, and Transfer Family
Pick the right batch mover for every source type you will ever meet on a lakehouse: a service-selection matrix with a decision flow; AWS DMS full load plus CDC into Amazon S3 with the real S3Settings (DataFormat=parquet, CdcMaxBatchInterval, CdcMinFileSize, IncludeOpForFullLoad, TimestampColumnName, TargetTablePrepMode, parallel load modes) and the S3-target limitations that silently fork your bronze history; Amazon AppFlow scheduled and event-triggered incremental pulls from Salesforce, Slack, ServiceNow and SAP; AWS DataSync agent versus agentless placement, Basic versus Enhanced task modes, schedules and integrity verification; AWS Transfer Family SFTP/FTPS/FTP/AS2 endpoints, workflows and SFTP connectors; S3 File Gateway for hybrid NFS writes; Snowball Edge's 2025-2026 wind-down; S3 Batch Operations for in-bucket reorgs; four idempotent landing patterns (deterministic keys, manifests, atomic promote, MERGE-from-staging) with a state machine; a fixed-hour versus per-GB cost-shape comparison; a worked DMS to bronze to Glue to Iceberg-silver flow; FINRA and Transport for NSW case material; a sourced October-2026 update box; and thirteen exam-style questions with three interactive checks.
Lesson 04 put a transactional table format on top of Amazon S3. This lesson is everything that happens before that: the byte-moving layer. A lakehouse with a perfect Iceberg silver layer and a badly chosen ingress service is a lakehouse with a two-week batch window, a duplicated bronze folder and a partner contract you cannot renegotiate.
The uncomfortable truth about batch ingestion is that the choice is almost never about throughput. Every service in this lesson can move the data. The choice is about who controls the source (you, a vendor API, a partner's SFTP client, a mounted share), whether changes must keep flowing, and how the bill is shaped: fixed hours versus gigabytes.
=====================================================================
BATCH INGESTION TOOLBOX β lesson 05 scope (as of Oct 2026)
---------------------------------------------------------------------
Databases (RDBMS) ......... AWS DMS β full load, full load + CDC,
CDC only -> Amazon S3 (CSV default,
parquet via DataFormat=parquet)
SaaS APIs ................ Amazon AppFlow β on demand / schedule /
event, IncrementalPullConfig, 15 GB per
Salesforce run, $0.001/run + $0.02/GB
File systems (NFS/SMB/
HDFS, other clouds) ....... AWS DataSync β agent or agentless,
Basic or Enhanced, hourly/daily/weekly,
TransferMode=CHANGED, checksum verify
Hybrid ongoing writes ..... S3 File Gateway β NFS v3/v4.1, SMB
v2/v3, 1 file = 1 object, async flush
Partner file feeds ........ AWS Transfer Family β SFTP/FTPS/FTP/
AS2 -> S3 or EFS, $0.30/h per protocol
Offline bulk .............. Snowball Edge = LEGACY (existing
customers only since 2025-11-07;
commercial EOS 2026-12-31) -> DataSync,
Data Transfer Terminal, partners
In-bucket reorg ........... Amazon S3 Batch Operations β $0.25/job
+ $1 per million objects
---------------------------------------------------------------------
Non-negotiable ............ S3 has no primary keys, no updates, no
referential integrity β every landing
must be IDEMPOTENT or you will double
rows on the first retry.
=====================================================================In this lesson you will:
- run the service-selection matrix, source type to service, and defend each row against the two runners-up;
- configure AWS DMS full load + CDC into Amazon S3:
DataFormat=parquet,CdcMaxBatchInterval/CdcMinFileSize,IncludeOpForFullLoad,TimestampColumnName,TargetTablePrepMode, parallel load modes andGlueCatalogGeneration; - name the S3-target limitations that decide whether your bronze layer is a clean landing or a duplicate generator;
- build AppFlow incremental pulls: schedules, events, filters, offsets and the 15 GB Salesforce ceiling;
- place DataSync agents, choose Basic vs Enhanced, schedule
TransferMode=CHANGEDruns and read the verification story; - stand up Transfer Family endpoints, workflows and connectors, and price them per protocol-hour;
- use S3 File Gateway for hybrid NFS/SMB writes and know its durability gap;
- state the Snowball Edge wind-down dates correctly (Snowcone 2024, new customers 2025-11-07, EOS 2026-12-31);
- apply the four idempotent landing patterns: deterministic keys, manifests, atomic promote, MERGE-from-staging;
- compare fixed-hour versus per-GB cost shapes before you commit to an architecture;
- walk a worked DMS β bronze β Glue β Iceberg-silver flow end to end;
- study two named AWS customer cases (FINRA, Transport for NSW) and a sourced October 2026 update box;
- practise with 13 exam-style questions plus three interactive checks.
1. Service selection: source type to service
1.1 The matrix
This is the whole lesson in one table. Every row is a constraint, not a preference: read the left column first.
Source type | Service | Shape of the move | Why this one |
|---|---|---|---|
Relational database (Aurora, RDS, on-prem Oracle / SQL Server / MySQL / PostgreSQL) | AWS DMS | Full load, full load + CDC, or CDC only β S3 | Log-based capture plus a documented S3 target with Parquet, batching, partitioning and optional Glue catalog generation |
SaaS API (Salesforce, Slack, ServiceNow, SAP SAPOData, Zendesk, Marketo, β¦) | Amazon AppFlow | On demand, on schedule, or on a source change event β S3 / Redshift | Managed connector profiles, field maps, filters and IncrementalPullConfig instead of hand-written pagination |
On-premises NFS / SMB / HDFS tree, or another cloud, that you must copy in bulk | AWS DataSync | Task between two locations, scheduled, TransferMode=CHANGED | Parallel pipeline, always-on checksum integrity, 1 file β 1 object with POSIX metadata preserved |
On-premises application that must keep writing to a share that lands in S3 | Amazon S3 File Gateway | Continuous NFS/SMB read-write with local cache, async flush to S3 | Files map 1:1 to objects (path = key), so existing applications do not change |
Partner or vendor that will only speak SFTP / FTPS / FTP / AS2 | AWS Transfer Family | Managed protocol endpoint backed by S3 or EFS, up to 3 AZs | The protocol survives; the storage becomes a lake. Optional post-upload workflows (PGP decrypt at $0.10/GB) |
Petabyte-scale offline or a site with no usable link | Ship-it or ship-to-facility | Snow Family is closed to new customers (2025-11-07) and reaches end of support 2026-12-31 | |
Re-tag / re-encrypt / re-locate / re-store objects already in the bucket | Amazon S3 Batch Operations | One job over a manifest of up to 4 billion objects | Purpose-built for in-bucket reorgs: not for row-level merges |
1.2 The decision flow
Two rules the flow encodes, both of which are examinable:
- Copy versus serve. DataSync copies from a location to a location and finishes. File Gateway serves a live share whose writes happen to land in S3. They solve different halves of "the data is on NFS".
- Protocol versus API. Transfer Family preserves a protocol the partner controls; AppFlow preserves a vendor's API with its rate limits and pagination. Neither substitutes for the other: AppFlow has no SFTP connector, and Transfer Family cannot page through Salesforce.
How to answer
Matching exercise with 6 pairs. Match each item on the left with its answer on the right.
Match each ingestion requirement to the single AWS service that satisfies it (as of Oct 2026):
Drag answers from here:
- π Did you know? DMS names its S3 output mechanically: full-load files carry an incremental hexadecimal counter (
LOAD00001.csv,LOAD00002.csv, β¦) while CDC files are named with timestamps (20141029-1134010000.csv), and every non-empty source table gets its own folder under the target path (AWS DMS S3 target docs, accessed 2026-10). That naming scheme is why an idempotent landing can be reasoned about at all; you can tell a load file from a change file from the key alone.
2. AWS DMS: full load + CDC into Amazon S3
2.1 The three task types, restated for the lakehouse
Task type | What moves | Lakehouse use |
|---|---|---|
Full load | Existing rows only, one pass | Seed bronze from a snapshot, or re-seed after a bad landing |
Full load + CDC | Existing rows and changes captured while the load runs | The default: seed bronze, then keep feeding it |
CDC only | Transaction-log changes from a chosen start point | Catch-up after a load, or a long-lived change feed |
For a lakehouse the target is not another database; it is a prefix on S3, which is where this differs from every migration tutorial you have read.
2.2 S3 target settings that actually matter
AWS documents the S3 target settings you will use in production. Grouped by purpose (AWS DMS S3 target docs and S3Settings API reference, accessed 2026-10):
Purpose | Setting | Value you will set |
|---|---|---|
Format | DataFormat | csv (default) or parquet: Parquet S3 target files supported from DMS 3.4.7 |
Location | BucketName, BucketFolder | The bronze prefix; layout becomes s3://bucket/[folder]/schema/table/ |
CDC file sizing | CdcMaxBatchInterval (seconds), CdcMinFileSize (KB) | AWS's own data-lake walkthrough: 3600 + 64000 to target β₯ 64 MB files for Athena |
Ordering | TimestampColumnName | Adds a source-commit timestamp column (e.g. last_update_time) for downstream dedup and sequencing |
PreserveTransactions + CdcPath | CSV pipelines only; preserves transaction order under CdcPath (3.4.2+) | |
Operation column | IncludeOpForFullLoad | Marks full-load rows with I so full-load and CDC files share a shape (3.1.4+, Parquet 3.4.7+) |
CdcInsertsOnly / CdcInsertsAndUpdates | Narrow the op column; mutually exclusive: both true is invalid | |
Partitioning | DatePartitionEnabled, DatePartitionSequence, DatePartitionDelimiter, DatePartitionTimezone | Date-partitioned bronze so Athena/Glue can prune |
Compression | CompressionType, ParquetVersion, RowGroupLength, MaxFileSize | Parquet sizing knobs |
Encryption | EncryptionMode, ServerSideEncryptionKmsKeyId | SSE-KMS on the landing |
Catalog | GlueCatalogGeneration | DMS creates Glue Data Catalog tables for the objects it identifies during migration |
Auth to S3 | ServiceAccessRoleArn | IAM role assumed by DMS to write to the bucket |
Load shape | TargetTablePrepMode, MaxFullLoadSubTasks, parallel-load modes | See Β§2.4 |
How to answer
Fill-in-the-blank exercise with 4 blanks. Type the missing words, then check your answer.
Complete the S3 endpoint configuration that AWS's own data-lake walkthrough prescribes (values as of Oct 2026):
blank=parquet makes DMS write Parquet instead of CSV; blank=3600 and blank=64000 target files of at least 64 MB for Athena; blank=true stamps every full-load row with the operation letter I so full-load and CDC files share a shape.
Word Bank, drag words into the blanks above:
2.3 The full-load + CDC timeline on S3
Phase 1 CAPTURE ....... CDC starts first; changes are cached on the
replication instance (memory, then disk spill)
Phase 2 FULL LOAD ..... existing rows written as LOAD<hex> files,
tables loading in parallel
Phase 3 APPLY ......... each table's cached changes are applied as
soon as that table finishes loading
Phase 4 STEADY STATE .. timestamp-named CDC files keep arriving;
watch CDCLatencySource / CDCLatencyTargetTwo things about S3 change the picture versus a database target:
- S3 has no primary keys, no updates and no referential integrity (AWS re:Post knowledge center, 2026-02-09). CDC files are therefore event files, not table states. Deduplication and ordering are your job downstream, which is exactly what
TimestampColumnNameand theopcolumn are for. - Transaction order is not preserved by default. The docs state that "by default for CDC, AWS DMS stores the row changes for each database table without regard to transaction order." For CSV you may set
PreserveTransactions=truewithCdcPath; for Parquet you addTimestampColumnNameand reconstruct order in the Glue job.
2.4 Parallel full load and target-table prep
Lever | What AWS documents |
|---|---|
Tables in parallel | MaxFullLoadSubTasks: AWS's Oracle-to-S3 walkthrough uses 49; parallel-load modes are ranges, partitions-optimized and partitions-auto, and "with the ranges option, full load finishes faster" for a partitioned table |
TargetTablePrepMode | DO_NOTHING, TRUNCATE (console name Truncate), DROP: the walkthrough chooses DO_NOTHING "because we want to control the retention of files from previous runs" |
LOB handling | Full LOB mode is not supported on S3 targets: pick a LOB Max Size instead |
Schema changes during full load | Not supported. DDL mid-load must wait for steady state |
Replication instance classes | T3, C5, C6i, R5, R6i (the docs table also lists R7i sizing up to dms.r7i.48xlarge, 192 vCPU / 1,536 GiB) |
Serverless option | DMS Serverless is AWS's recommendation "for heterogeneous migrations or continuous data replications with data fluctuations" (1 DCU = 2 GB RAM) |
Validation | S3 target validation needs DMS 3.5.0+ with DataFormat=parquet, runs once a day at 00:00 UTC via Athena CTAS, caps Athena bucketed tables at 100,000 buckets, and fails on Lake Formation-managed buckets |
β οΈ Six S3-target limitations that decide whether bronze is trustworthy (AWS DMS S3 target docs, accessed 2026-10):
- Do not enable versioning on the DMS target bucket: endpoint test connections can fail on an S3
list-objecttimeout. BatchApplyis not supported for an S3 endpoint and "might result in loss of data": leave it off.TargetTablePrepMode=DO_NOTHINGcan write duplicates if the task stops and resumes abruptly during full load. AWS's guidance: preferTRUNCATE_BEFORE_LOAD, and before restarting, manually delete the previously created full-load files.- Two tasks replicating the same source table into the same target bucket write to the same file. One source table, one task, one prefix.
- Schema changes during CDC are only half-recorded: truncate/drop/create/rename table, add/drop/rename column and change column type are captured as DDL, but "no ALTER statement is recorded in the target S3 bucket, and AWS DMS does not alter previously created records to match the new structure." New files simply use the new shape.
- Validation is not a row count. Daily at midnight UTC only, Parquet only, and it breaks on Lake Formation-managed buckets.
That fifth bullet is the single most important sentence in this lesson: bronze is a schema-on-read surface. Old files keep old shapes forever. Only an Iceberg silver layer plus a Glue catalog entry restores schema-on-write semantics (lesson 04); which is precisely the flow in Β§11.
2.5 Worked example E1: Athena-friendly CDC sizing (as of Oct 2026)
AWS's own SQL Server-to-data-lake step-by-step tells you the two settings and the reason:
"Because we plan to use Amazon Athena to query data from our Amazon S3 bucket, we need to make sure that our target file size is at least 64 MB. Specify the following endpoint settings:
CdcMaxBatchInterval=3600andCdcMinFileSize=64000." (AWS DMS SBS, accessed 2026-10)
Worked example E1 - sizing a 50 GB full load and one hour of CDC
----------------------------------------------------------------
Source .................. RDS PostgreSQL, table orders, 50 GB,
PK order_id, updated_at
Endpoint ................ DataFormat=parquet, ParquetVersion=
PARQUET_2_0, IncludeOpForFullLoad=true,
TimestampColumnName=cdc_ts,
DatePartitionEnabled=true (day),
CdcMaxBatchInterval=3600, CdcMinFileSize=
64000 (= 64,000 KB target)
Athena floor ............ >= 64 MB per file (AWS SBS guidance)
Full load files ......... 50 GB = 51,200 MB
51,200 / 64 = 800 files
CDC window .............. 3,600 s x 100 rows/s = 360,000 events
-> about 1 Parquet file per hour, because
AWS notes Parquet files land SMALLER than
CdcMinFileSize (compression ratio varies),
while CSV files equal CdcMinFileSize
Parallelism ............. MaxFullLoadSubTasks (tables in parallel)
x ranges / partitions-optimized /
partitions-auto for a partitioned table
Gotcha .................. a stalled full load + DO_NOTHING restart
re-writes LOAD* files -> duplicatesThe examinable chain: Athena wants β₯ 64 MB files β CdcMinFileSize=64000 KB and CdcMaxBatchInterval=3600 s β Parquet lands smaller than the target because of compression β so a naive "one file per hour" assumption is wrong for Parquet and right for CSV.
3. Amazon AppFlow: SaaS to S3 with incremental pulls
3.1 Connectors, triggers, and the incremental contract
AppFlow's source ConnectorType values include Salesforce, Slack, Servicenow, SAPOData (SAP), Zendesk, Marketo, Googleanalytics, Datadog, S3, Redshift, Snowflake, CustomConnector and EventBridge, among others; destinations for Salesforce flows include Amazon S3, Amazon Redshift, Amazon EventBridge, Snowflake and Zendesk (CloudFormation SourceFlowConfig docs and the Salesforce connector guide, accessed 2026-10).
Lever | Behaviour (as of Oct 2026) |
|---|---|
Trigger | On demand, on a schedule, or on a source change event ("an event-triggered flow runs when Amazon AppFlow detects a change to the target data in the CRM storage service") |
Incremental pull | IncrementalPullConfig: transfers "only the records that have been added or changed since the last successful flow run" |
First scheduled run | "The first schedule-triggered flow will pull 30 days of past records at the time of the first flow run" |
Offset | Guards source-side timestamping lag: records new or changed between T0 β t and T1 β t are imported at T1 |
Pruning / gating | In-flow Filters ("specify what data the flow transfers") and validations run before landing |
Salesforce ceiling | 15 GB per flow run β 7.5 million records at 2 KB average (records can be up to 4 KB): split larger pulls with filters |
Profile quota | Soft quota of 100 connector profiles per AWS account |
Prerequisite | Salesforce needs a Connected App; ServiceNow needs "no pre-requisite configuration for either AWS or ServiceNow" |
3.2 Worked example E2: what a scheduled Salesforce pull costs (as of Oct 2026)
AWS's pricing page publishes the arithmetic rather than a rate table. From the us-east-1 and Frankfurt examples (accessed 2026-10): $0.001 per successful flow run, $0.02 per GB processed, and, critically, "Flow runs to check for new data will count towards your flow run costs, even if no new data is available."
Worked example E2 - hourly Salesforce -> S3 incremental flow
------------------------------------------------------------
Cadence ............. every hour, 24 x 30 = 720 runs / month
+ 1 event-triggered run per business day
= 22 more runs -> 742 runs
Flow-run cost ....... 742 x $0.001 = $0.742 -> $0.74
Volume .............. 600 GB changed / month
Data cost ........... 600 / 1 x $0.02 = $12.00
Monthly total ....... $0.74 + $12.00 = $12.74
Published anchors ... "1000 x $0.001 = $1 a day" (AWS example)
Frankfurt: "10 GB / (1 GB) x $0.02 = $0.20"
Empty runs .......... 742 checks bill even if 0 rows changed
Salesforce cap ...... 600 GB / 15 GB = 40 runs minimum if the
pull were one big sweep; filters keep each
run comfortably under 15 GB / 7.5M recordsTwo design consequences fall out of the pricing page, not out of the feature list:
- A poll cadence is a line item. Checking every five minutes costs 8,640 runs/month in a 30-day month, whether or not anything changed. Set the schedule from the freshness the consumer needs.
- The 30-day first pull is a deduplication event. Your bronze layer receives a month of history on run one and deltas thereafter, so the landing must be idempotent (Β§9) or day-one bronze will double-write anything that also arrived through another path.
β οΈ Do not claim Parquet landing from AppFlow without re-checking the S3 output format docs. The official pages retrieved for this lesson show fileType: CSV and describe CSV/JSON output; Parquet output was not confirmed in the retrieved material. Treat AppFlow as a CSV/JSON lander unless you have verified otherwise for your Region and connector, and do the format conversion in the Glue step instead.
- π Did you know? AppFlow bills the check, not just the change: AWS's own pricing page states that runs "to check for new data will count towards your flow run costs, even if no new data is available." For SAP flows AWS shows a concurrency multiplier instead, "you apply 9 concurrent processes β¦ (1+9) x $0.001 (flow cost)", so parallelism multiplies run charges rather than saving them (AWS AppFlow pricing, accessed 2026-10).
4. AWS DataSync: agents, task modes, schedules, verification
4.1 Agent or agentless?
A DataSync task copies between two locations. Whether you need an agent is decided by where those locations live (AWS DataSync docs, accessed 2026-10):
Location pair | Agent needed? |
|---|---|
NFS / SMB / HDFS on-premises β S3, EFS, FSx | Yes: a VM agent (ESXi, KVM, Nutanix AHV, Hyper-V) or an AMI on EC2 |
Amazon S3 β Amazon S3 in the same AWS account | No |
Amazon S3 β a different AWS storage service across accounts | No |
Amazon S3 β a different cloud | No for Enhanced mode |
Rules that bite in production:
- A location can hold up to four Basic-mode agents and up to four Enhanced-mode agents, and "All the agents associated with a location must be online before you can start your transfer task. If one of the agents is offline, you can't run your task." Multi-agent gives speed, not failover.
- Enhanced-mode agents and Basic-mode agents are not interchangeable for the same location.
- NFS defaults to version 4.1 (also 4.0 and 3.x) over TCP 2049 (plus 111 for v3); destination exports need
no_root_squash, and DataSync does not copy NFSv4 ACLs.
4.2 Basic versus Enhanced task modes
Basic | Enhanced | |
|---|---|---|
Pipeline | Sequential prepare β transfer β verify | Parallel list, prepare, transfer and verify |
Verification | Verifies all data by default | Verifies only transferred data |
Object-count quota | 50 million items/task (on-prem β AWS), 25 million (AWS β AWS) | Virtually unlimited |
Memory guidance | Allocate 64 GB RAM to the agent above 20 million files/objects/directories | : |
Pricing shape | $0.0125/GB copied (pricing-page example) | $0.015/GB + $0.55 per task execution (pricing-page example) |
Integrity | Checks always run during transfer (checksum + metadata compare) | Same |
Task options worth memorising: TransferMode=CHANGED, VerifyMode=ONLY_FILES_TRANSFERRED, ObjectTags=PRESERVE, LogLevel=TRANSFER, plus filters/manifests and optional deletion mirroring (delete in the destination what no longer exists in the source). Scheduling is hourly, daily or weekly directly in the console.
4.3 Worked example E3: 20 TB from NFS to S3, Basic vs Enhanced (as of Oct 2026)
Using the rates printed in AWS's own worked examples on the DataSync pricing page (accessed 2026-10):
Worked example E3 - 20 TB NFS -> S3, one-off then daily deltas
----------------------------------------------------------------
Basic mode
20 TB x 1024 GB = 20,480 GB
transfer ...... 20,480 x $0.0125 = $256.00
execution fee . none
quota check ... 20,480 GB of many small files could exceed the
50 million item/task ceiling -> shard the tree
into <50M-item tasks (64 GB agent RAM above 20M)
Subtotal ...... $256.00 + S3 PUT/GET requests
Enhanced mode
transfer ...... 20,480 x $0.015 = $307.20
executions .... 30 daily runs x $0.55 = $16.50
Subtotal ...... $323.70 + S3 PUT/GET requests
Delta ........... Enhanced costs $67.70 more per month here, and
buys: parallel pipeline, virtually unlimited
object counts, per-execution metrics, and
verify-only-transferred instead of verify-all
AWS anchor ...... "(50 TB * 1024 GB copied using DataSync *
$0.015/GB) ... (1 task execution * $0.55) =
... $797.58" (Enhanced)
"(50 TB copied into S3 * 1024 GB * $0.0125/GB)
= $656.38" (Basic)Read the trap before you copy anything. AWS's Storage Blog warns that objects seeded into a bucket by other tools lack DataSync metadata, so DataSync performs HEAD + GET + an in-place copy, and objects in archive storage classes cannot be GET at all, forcing a full re-transmission over the wire (plus a new version if versioning is on). The blog's advice: "use DataSync to perform the initial transfer to S3 whenever possible" and consider suspending S3 versioning on the bucket. Do the first sync with DataSync into an empty bucket.
- π Did you know? DataSync's "changed since last run" detection depends on DataSync's own metadata. AWS's blog states that DataSync "automatically copies each file as a single S3 object in a 1:1 relationship, and preserves POSIX metadata on the source file as Amazon S3 object metadata", and that objects uploaded by other tools trigger the HEAD+GET+COPY path (AWS Storage Blog, 2021-08-24). A hybrid pipeline where a partner's SFTP feed and DataSync both write one prefix will therefore pay for re-copies forever.
5. AWS Transfer Family: partner protocols into the lake
5.1 What it is
Transfer Family is a fully managed endpoint speaking SFTP (v3), FTPS, FTP, AS2 or a browser, backed by Amazon S3 or Amazon EFS, "supports up to 3 Availability Zones and is backed by an auto scaling, redundant fleet."
Design point | Options and limits (as of Oct 2026) |
|---|---|
Endpoint type | Public (SFTP only), VPC, Internet (SFTP, FTPS, AS2), VPC, Internal (SFTP, FTP, FTPS, AS2) |
Authentication | Service-managed users, AWS Managed Microsoft AD, or API Gateway + Lambda: password authentication needs AD or the custom wiring |
Post-upload workflows | PGP decrypt / validate / notify: $0.10/GB processed |
SFTP connectors | Pull from or push to remote SFTP servers: $0.001 per connector call + $0.40/GB; 100/account, 150 GiB/file, 1,000 queued ops, 50 MBps/account, 5 parallel sessions, 100 paths/s |
Sessions / idle | 10 concurrent multiplexed SFTP sessions per connection; 1,800 s (30 min) idle timeout |
File size | 5 TB (the S3 object ceiling) |
S3 semantics leak | Rename "Supported for files only. Renaming that would overwrite an existing file is not supported"; SETSTAT unsupported with S3 |
β οΈ Transfer Family bills per enabled protocol-hour, even when idle. AWS's worked example: SFTP at **0.30 Γ 24 Γ 30 = 0.04 Γ GB` for data moved. Enabling SFTP and FTPS on the same endpoint doubles the fixed charge. Two client-side traps travel with it: multi-connection single uploads against S3 can "fail in unpredictable ways" and leave orphaned multipart uploads that incur Amazon S3 charges; and because the protocol maps onto S3, a rename that would overwrite is rejected.
5.2 Worked example E4: the partner feed bill (as of Oct 2026)
Worked example E4 - 30 partners on one SFTP endpoint (us-east-1)
----------------------------------------------------------------
Endpoint ............. SFTP only, always on
$0.30/h x 24 x 30 = $216.00
Data .................. 400 GB uploads + 100 GB downloads
500 GB x $0.04 = $ 20.00
Workflow .............. 50 GB PGP-decrypted at $0.10/GB
50 x $0.10 = $ 5.00
Monthly total ......... $241.00
Shape ................. fixed $216 = 89.6% of the bill; at this
volume the protocol-hour, not the data,
dominates
Published anchor ...... dual-protocol 1,000-user example:
"$216 + $180 + $216 + $360 = $972"
(two protocols, two endpoint flavours)
Lesson ................ enabling a second protocol "to be safe"
costs $180/month before a byte moves6. Amazon S3 File Gateway: hybrid NFS writes that land in S3
An S3 File Gateway appliance (VM, hardware or EC2) exports NFS v3/v4.1 or SMB v2/v3 shares; "Files written to a file share become objects in Amazon S3, with the path as the key. There is a one-to-one mapping between files and objects."
Property | Detail (as of Oct 2026) |
|---|---|
Encryption | SSE-S3 by default; SSE-KMS and DSSE-KMS optional: "make sure that your file share uses the same encryption type as the Amazon S3 bucket" |
Integrity | File Gateway populates the Content-MD5 header; all transfer over HTTPS |
Write path | Application writes are stored in the cache synchronously, then uploaded to S3 asynchronously |
Bucket mapping | One file share β one bucket; multiple shares may share a bucket only with "a unique, non-overlapping S3 bucket prefix" |
Metadata capacity | Default gateway capacity Small = metadata for up to 5 million files; 8 S3 upload threads by default |
Price | $0.01/GB written to AWS, first 100 GB/month free per gateway, capped at $125 per gateway per month; reads are free (S3 requests/storage still apply) |
Scope | "S3 File Gateway is not designed to act as a full enterprise NAS replacement. S3 File Gateway emulates a file system, but it is not a file system." |
The durability gap is the operational point: writes are durable only after the cache flushes, so AWS instructs you to "make sure that the CachePercentDirty CloudWatch metric is 0" before stopping the host that runs the gateway. And with versioning on, a single file write creates two object versions: one for the data, one for the metadata update.
When to pick File Gateway over DataSync: if an application must keep writing through a POSIX path, it is File Gateway. If you need to copy a tree on a schedule, it is DataSync. Using DataSync to fake a writable share, or File Gateway to fake a migration, both produce the wrong failure mode.
7. Offline bulk: the Snowball Edge pattern (and its 2026 status)
Teach the pattern, a shipped disk that lands verified bytes in S3, but teach the product status correctly, because most content on the open web is now stale.
Milestone | Date | Consequence |
|---|---|---|
Snowcone discontinued | 2024-11-12 | Existing-customer support ended 2025-11-12 |
Snowball Edge closed to new customers | 2025-11-07 | AWS directs new bulk-offline needs to AWS DataSync, AWS Data Transfer Terminal, AWS Partner solutions |
No Snow Family devices for new customers to order | current | "AWS will no longer offer any AWS Snow Family devices for new customers to order" |
Commercial-Region end of support | 2026-12-31 | Applies to Storage Optimized and Compute Optimized devices |
Device and price anchors for anyone maintaining an existing deployment (AWS Snowball pricing, us-east-1, accessed 2026-10): Storage Optimized 210 TB usable; On-Demand Job Fee up to 100 TB (includes 15 days) $1,800; 101 TB: 210 TB $3,200; $250 per day beyond 15 days; $9,885 per month; 1-year commitment upfront $97,268; S3-compatible on-device storage $0.01 per GB-month or $0.12 per GB-year. Compute Optimized reaches 104 vCPUs, 416 GB memory and 28 TB of dedicated NVMe SSD.
- π Did you know? The offline pattern outlives the product. With Snowcone gone and Snowball Edge restricted, AWS's own migration note points at DataSync for online transfers, Data Transfer Terminal for secure physical uploads, and partners: the architecture question ("how do 500 TB reach S3?") still has the same three answers, only the order of preference changed (AWS Snow device updates, 2024-11-12; Snowball Edge availability change docs, accessed 2026-10).
8. Amazon S3 Batch Operations: reorganising what already landed
S3 Batch Operations is the repair tool for a landing that went wrong, and the migration tool for a prefix layout you are changing. One job runs one operation over a manifest:
- copy objects, update server-side encryption, set object tags or ACLs, initiate restores from S3 Glacier Flexible Retrieval, invoke an AWS Lambda function, Object Lock and Batch Replication;
- default manifest size 4 billion objects, rising to 20 billion for Copy, Object Tagging, Object Lock, Lambda invoke and Batch Replication;
- manifest format
S3BatchOperations_CSV_20180820, commonly generated from S3 Inventory; - price: $0.25 per job + $1.00 per million objects processed (AWS S3 pricing, accessed 2026-10).
8.1 Worked example E5: repairing a mis-tagged landing (as of Oct 2026)
Worked example E5 - 12,000,000 objects tagged after a bad job
----------------------------------------------------------------
Job fee ................. 1 x $0.25 = $ 0.25
Per-object .............. 12,000,000 / 1,000,000 x $1.00
= 12 x $1.00 = $ 12.00
Subtotal ................ = $ 12.25
(+ S3 PUT tagging requests for the objects)
Published anchor ........ AWS's own 1,000,000-object example
totals "$1.25"
Contrast ................ a per-object SDK loop is the same
12M PUTs but with your own retries,
throttling and no completion report
Scope ................... object-level ONLY - tags, keys,
encryption, ACLs, restore, Lambda.
Row-level merges belong to Iceberg
(lesson 04), not to Batch Operations9. Idempotent landing: the four patterns
Everything so far produces files. S3 will happily accept the same file twice, and AWS's own guidance is blunt: "Amazon S3 doesn't support primary keys, updates, or referential integrity." So the landing layer, the part between the mover and the table format, needs a retry-safe contract.
# | Pattern | Mechanism | Failure it defeats |
|---|---|---|---|
1 | Deterministic keys | Encode source, table, partition date and a content/batch hash in the key so a retry overwrites instead of appending | Duplicate objects from a retried upload |
2 | Manifest files | Write a _SUCCESS/manifest listing objects, row counts and checksums; consumers read a batch only when its manifest is complete | Downstream jobs reading a half-written batch (the Step Functions + SQS + manifest pattern) |
3 | Atomic promote | Write to staging/β¦, then server-side copy (CopyObject) to landed/β¦ | Readers seeing partial files; note Transfer Family's rename is non-overwriting, so promotion is a copy, not a move |
4 | MERGE from staging | Land raw files immutably, then MERGE INTO silver USING staging on business key + timestamp dedup | A replayed CDC file changing silver twice: the commit stays idempotent |
9.1 Ordering the steps
How to answer
Ordering exercise with 6 items. Move them into the correct order, then check your answer.
Order the idempotent landing sequence from raw write to a committed silver row:
9.2 The MERGE that makes replay safe
From AWS's own CDC-into-Iceberg recipes (Big Data Blog, 2022-06-15 updated May 2023; 2023-02-14): DMS supplies the op attribute for incremental CDC data but not for the initial load unless you set IncludeOpForFullLoad=true; the Glue job deduplicates on the last_update_time column that TimestampColumnName added, then runs
MERGE INTO silver.orders s
USING staged_orders d
ON s.order_id = d.order_id
WHEN MATCHED AND d.op = 'D' THEN DELETE
WHEN MATCHED THEN UPDATE SET s.status = d.status, s.updated_at = d.updated_at
WHEN NOT MATCHED THEN INSERT (order_id, status, updated_at)
VALUES (d.order_id, d.status, d.updated_at);9.3 Worked example E6: what a replay costs you (as of Oct 2026)
Worked example E6 - the same CDC batch delivered twice
----------------------------------------------------------------
Batch ............. CDC file with 5,000 events for 800 distinct
order_ids, cdc_ts stamped by TimestampColumnName
Run 1 - naive INSERT INTO
silver rows +5,000 -> total 5,000 for these keys
Run 2 - replay of the SAME file
silver rows +5,000 -> total 10,000 (doubled)
Athena count(*) is now wrong for every
downstream dashboard, silently
Run 1 - dedupe then MERGE
ROW_NUMBER() OVER (PARTITION BY order_id
ORDER BY cdc_ts DESC) = 1 -> 800 rows
MERGE: 320 'D' deletes, 480 I/U upserts
silver rows for these keys = 800 net
Run 2 - replay of the SAME file
dedupe again -> same 800 rows
MERGE matches identically -> net change 0
Result: idempotent commit, row count unchanged
Rule .............. "Only one record in the source data can
update any given row of the target table, or
else an error will be thrown" - dedupe first,
every time, before MERGE ever runs- π Did you know? A DMS task restart can manufacture duplicates on its own. AWS's guidance for
TargetTablePrepMode=DO_NOTHINGis that a task stopping during full load "writes the full load files again when it restarts", so you must either switch toTRUNCATE_BEFORE_LOADor manually delete the earlierLOAD*files before restarting (AWS re:Post, 2026-02-09). Idempotency is not only about your Glue job; it is about the mover's restart behaviour too.
10. Cost shape: fixed-hour versus per-GB
Before you commit to an architecture, work out which of these three shapes the bill takes. They behave completely differently as volume grows.
=====================================================================
COST SHAPES (published rates, us-east-1 examples, as of Oct 2026)
---------------------------------------------------------------------
FIXED-HOUR / FIXED-CAPACITY
Transfer Family .... $0.30 per enabled protocol-hour
-> $216/month per protocol, idle or not
AWS DMS ............. replication-instance hours (or DCUs for
Serverless; 1 DCU = 2 GB RAM) + storage
(100 GB GP2 on C4/R4/R5, 50 GB on T2/T3)
+ Multi-AZ recommended for ongoing work
Snowball Edge ....... $1,800 (<=100 TB, 15 days) / $3,200
(101-210 TB) / $250 per extra day
/ $9,885 per month
PER-GB / PER-UNIT
DataSync ............ Basic $0.0125/GB; Enhanced $0.015/GB
+ $0.55 per task execution
AppFlow ............. $0.001 per successful run + $0.02/GB
S3 Batch Operations . $0.25 per job + $1.00 per million objects
File Gateway ........ $0.01/GB written, first 100 GB free,
$125/gateway/month cap, reads free
HYBRID (fixed floor + variable)
Transfer Family data $0.30/h/protocol + $0.04/GB moved
Transfer workflows ... $0.10/GB processed (e.g. PGP decrypt)
SFTP connectors ...... $0.001/call + $0.40/GB
=====================================================================The worked example in Β§5.2 is the proof: a 500 GB partner feed on Transfer Family costs $241, of which $216 (89.6%) is protocol-hour. The same 500 GB through DataSync at the Basic rate would be 500 Γ $0.0125 = $6.25. Transfer Family is still the correct answer, because the partner is the constraint, but you should know you are buying protocol compatibility, not bandwidth.
β οΈ Do not quote a DMS instance $/hour from memory. AWS renders the DMS on-demand instance table dynamically, and the figures captured for this lesson could not be verified from the pricing page (they appear only in third-party blogs). The verified structure is: instance classes (T3, C5, C6i, R5, R6i, R7i), included storage (100 GB GP2 on C4/R4/R5 classes, 50 GB on T2/T3), $0.075 per vCPU-hour for T3 CPU credits in unlimited mode, 1 DCU = 2 GB RAM for DMS Serverless, "all data transfer into AWS DMS is free", and same-AZ DMSβRDS traffic free. Pull the live rate from aws.amazon.com/dms/pricing/ before you model a bill.
11. Worked end-to-end: DMS β bronze β Glue β Iceberg silver
11.1 The flow
11.2 The outline, step by step (as of Oct 2026)
Worked example E7 - RDS orders (50 GB) into an Iceberg silver table
--------------------------------------------------------------------
Step 1 DMS ENDPOINT (S3 target)
DataFormat=parquet ......... Parquet from DMS 3.4.7
ParquetVersion=PARQUET_2_0
IncludeOpForFullLoad=true .. full-load rows carry 'I',
so full-load and CDC share a
shape (3.1.4+, parquet 3.4.7+)
TimestampColumnName=cdc_ts . source commit timestamp for
dedup + ordering
DatePartitionEnabled=true .. day partitions for pruning
CdcMaxBatchInterval=3600 ... one hour of change per file
CdcMinFileSize=64000 ....... >= 64 MB target for Athena
ServiceAccessRoleArn ....... IAM role to write the bucket
GlueCatalogGeneration ...... optional Glue tables created
as DMS migrates
Step 2 TASK
Type: Full load, ongoing replication
TargetTablePrepMode: DO_NOTHING (control retention) - and
therefore NEVER restart mid-full-load without cleaning
the prior LOAD* files
MaxFullLoadSubTasks / ranges / partitions-auto for the
partitioned full load; LOB Max Size (no Full LOB mode)
Step 3 ORCHESTRATION
S3 event -> SQS -> Step Functions; SQS holds batch order,
Step Functions fans out per table, Glue job bookmarks
track which CDC files are new
Step 4 GLUE JOB (silver)
read bronze Parquet -> dedup on (order_id, max cdc_ts)
-> split op: D vs I/U -> MERGE INTO silver.orders
-> schema evolution via Iceberg ADD/DROP COLUMN
Step 5 VERIFY
Athena CTAS sanity counts; DMS S3 validation if you want
it (3.5.0+, parquet, daily 00:00 UTC, not on LF buckets);
VACUUM weekly to expire snapshots
Numbers . 50 GB / 64 MB = ~800 full-load files
3,600 s x 100 rows/s = 360,000 CDC events/hour
Parquet compresses below CdcMinFileSize -> fewer,
smaller files than the CSV equivalentEvery ingredient in that block is drawn from AWS's published patterns: Step Functions + SQS ordering with Glue jobs creating the silver layer (Big Data Blog, 2024-10-30), a Glue job bookmark driving incremental MERGE with last_update_time dedup (2023-02-14), and two DMS tasks splitting full-load and date-partitioned CDC folders for an Athena-native MERGE (2023-04-27).
2026 Updates (as of October 2026)
What changed around batch ingestion that this lesson depends on: each line sourced and dated:
- 2025-05-14: Firehose gained a Glue multi-catalog hierarchy. The Firehose document history records "Glue multi-catalog hierarchy" support, so a delivery can target a non-default catalog such as S3 Tables rather than only the account's default Glue catalog (Amazon Data Firehose User Guide, document history, accessed 2026-10-11). Relevance: the destination side of ingestion now has a managed Iceberg option alongside DMS β bronze β Glue.
- 2025-01-27, Amazon S3 Metadata is GA. "S3 Metadata makes it easy to query and filter S3 object metadata using SQL⦠you can query object metadata using Amazon Athena", object metadata lands in S3 Metadata tables that appear in the Glue Data Catalog / Athena (AWS News Blog, 2025-01-27). Relevance: auditing what a landing actually produced (sizes, keys, counts) without a full S3 Inventory cycle.
- 2026-08-21: AWS Glue 6.0 is GA with a 30% price reduction. "AWS Glue 6.0 is now generally available, delivering a 30% price reduction and introducing full support for Apache Iceberg v3" with Spark 4.1, Python 3.13 and Spark Declarative Pipelines for built-in orchestration (AWS News Blog, 2026-08-21). Relevance: the MERGE stage of Β§11 gets cheaper and can carry its own orchestration.
- 2025-11-07: Snowball Edge closed to new customers. "AWS Snowball Edge devices will only be available to existing customers. New customers should explore AWS DataSync for online transfers, AWS Data Transfer Terminal for secure physical transfers, or AWS Partner solutions" (AWS Snow device updates, 2024-11-12 notice; Snowball Edge availability docs, accessed 2026-10).
- 2026-12-31: Snowball device end of support in commercial Regions. "On December 31, 2026, AWS will discontinue support for AWS Snowball devices in all AWS commercial Regions. This includes both the AWS Snowball Edge Storage Optimized and Compute Optimized devices" (aws.amazon.com/snowball, accessed 2026-10). Any runbook that still says "order a Snowball" needs rewriting this quarter.
Real-World Case Studies
AWS publishes what these patterns look like in production. Every figure below is customer- or AWS-claimed and unaudited, with the source named so you can check it: the examinable point is the pattern, not the marketing.
Case A, FINRA: validating and cataloguing files at regulator scale
Element | Detail |
|---|---|
Customer | FINRA: the US financial-market regulator, running market surveillance at national scale |
Challenge | Fixed-capacity on-premises analytics could not keep pace with market data while meeting regulatory audit and lineage duties |
Ingestion shape | Market data arrives from exchanges as files over SFTP/HTTPS, validated (AWS lists AWS Lambda for file validation among the services) and then catalogued before analytics reads it: with Amazon S3 as the landing and archive layer |
Services | Amazon S3 data lake + archive, AWS Lambda file validation, Amazon EMR (Hive, Presto, Apache HBase on S3), EC2 Spot, Redshift marts, KMS, and FINRA's own open-source herd catalog as the single source of truth |
Outcomes (as AWS reported in 2016 to 2017) | ~6 TB and 37 billion records on an average day, 75 billion+ records on busy days; 600+ TB with "trillions of records" queryable interactively; over 60% cost savings moving HBase onto S3; cluster ready in under 30 minutes versus "almost two days"; most queries under 3 seconds |
Lesson here | Ingest, validate, catalog, then process, and where possible "process directly against data on Amazon S3" instead of copying it into an engine-local store first |
Source | AWS Public Sector Blog, 2017-10-03; AWS Big Data Blog, 2016-11-21 (accessed 2026-10) |
"We extended the data lake pattern with EMR, Hbase, and Amazon S3 to allow interactive random access queries across trillions of records spanning 600+ terabytes of data.": AWS Public Sector Blog, 2017-10-03
Read FINRA as a batch-ingestion case, not just an architecture case: files land, get validated before anything reads them (that is your manifest/verify step), get catalogued (your Glue entry), and only then are queried. The validation-before-read discipline is the same regardless of whether the mover is Transfer Family, DataSync or DMS.
Date honesty: these are 2016 to 2017 figures for a platform that has since changed: treat them as historical milestones, never as FINRA's current state.
Case B, Transport for NSW: 400+ ingestion workflows off licensed ETL
Element | Detail |
|---|---|
Customer | Transport for NSW: Australian transport agency, 25,000+ employees, 2M+ passengers/day |
Challenge | More than 400 legacy ETL ingestion workflows on a third-party licensed platform, with multi-month lead times to add new feeds and key-person dependency on legacy expertise |
Services | AWS Glue (serverless data integration, Python), AWS Step Functions (orchestration and monitoring), Amazon S3 (data lake foundation), RDS for backward compatibility |
Outcomes (customer-reported) | Annual data-integration costs cut by ~80%; new ingestion jobs build-and-deploy in "Less than 3 weeks" (down from several months); 30+ team members trained; expertise distributed beyond legacy specialists |
Lesson here | The batch-ingestion bill is rarely just the mover's bill: licensing, lead time and key-person risk are part of the cost shape (Β§10) |
Source | AWS case study, undated, accessed 2026-10-11 |
Case | Pattern it demonstrates | Section |
|---|---|---|
FINRA | Files in β validate β catalog β query on S3; process against the lake instead of copying into an engine | Β§1, Β§9 |
Transport for NSW | Replacing licensed ETL workflows with serverless ingestion + orchestration; cost shape beyond $/GB | Β§10 |
- π Did you know? Transport for NSW's "30+ team members trained" is the operational half of the cost argument: AWS notes the team "was also able to distribute expertise across several existing team members" once the platform was Python-based Glue rather than a specialist tool (AWS case study, accessed 2026-10-11). The 80% cost cut is the headline; the removal of the key-person dependency is usually the reason such migrations stick.
Practice Questions
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A DMS task lands CDC into Amazon S3 and Athena queries keep scanning tiny files. AWS's own data-lake walkthrough prescribes two S3Settings to fix this. Which pair is correct (as of October 2026)?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A source database gains a new column while a DMS full-load task is still running, and later ALTERs happen during CDC. What lands in the S3 bronze prefix?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A DMS full-load task using TargetTablePrepMode=DO_NOTHING stops halfway through a 50 GB load and is restarted. What should the operator do first (as of October 2026)?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A team schedules an AppFlow flow from Salesforce to Amazon S3. Which statement about incremental pulls and cost is correct (as of October 2026)?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A 40 TB on-premises NFS tree must be copied to S3 once and then synchronized hourly, with only changed files transferred. Which configuration is correct (as of October 2026)?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
One DataSync location is served by four agents, and one of them goes offline. What happens when you start the task?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
Thirty partners upload 400 GB and download 100 GB each month over a single SFTP Transfer Family endpoint, and 50 GB is PGP-decrypted by a workflow. What is the monthly total in us-east-1 (as of October 2026)?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A NEW AWS customer in October 2026 needs to move 80 TB from a site with a usable network link but limited bandwidth. Which approach is correct?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
Twelve million objects were tagged incorrectly by a previous job. What is the cost of a single S3 Batch Operations job that fixes the tags (as of October 2026)?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
An application writes through an S3 File Gateway NFS share. An operator wants to stop the gateway host for maintenance. What must be true first?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A CDC file is delivered twice to bronze and the Glue job runs twice. Which design makes the silver table correct after both runs?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A team wants DMS to create Glue Data Catalog tables for the objects it identifies while replicating to S3, and wants to validate the replicated data. Which combination is correct (as of October 2026)?
How to answer
Multiple-choice question with 4 options. Select one option, then choose Check Answer.
A low-volume partner feed moves 1 GB per month. Which cost-shape statement is correct (as of October 2026)?
β οΈ Pattern traps for this lesson: walk this list before you design anything:
- S3 has no primary keys, updates or referential integrity. CDC files are event files. Dedup and ordering are your job:
TimestampColumnNameplus MERGE, neverINSERT INTO. DO_NOTHING+ a restart = duplicates. Clean up priorLOAD*files or useTRUNCATE_BEFORE_LOADbefore restarting a full load.BatchApplyon an S3 target can lose data. Leave it off. Do not enable versioning on a DMS target bucket either (list-object timeouts break endpoint tests).CdcInsertsOnlyandCdcInsertsAndUpdatesare mutually exclusive, and forgettingIncludeOpForFullLoadbreaks any MERGE that branches onop.PreserveTransactions(CSV) βTimestampColumnName(Parquet). They solve different halves of ordering and conflict withDatePartitionEnabled/AddColumnName.- Bronze is schema-on-read. DMS will not rewrite old files after a DDL; only an Iceberg silver + Glue catalog gives you schema-on-write.
- DMS S3 validation is not a row count: daily at 00:00 UTC, Parquet only, Athena bucket cap 100,000, and it fails on Lake Formation-managed buckets.
- DataSync's "changed" detection depends on DataSync's own metadata: foreign-seeded objects get HEAD+GET+COPY, archive-tier objects get re-uploaded; do the first sync with DataSync into an empty bucket.
- Basic-mode quotas bite silently (50M / 25M items per task) and all agents on a location must be online to start a task.
- Transfer Family bills protocol-hours while idle; enable only the protocols partners actually use, and stop clients from multi-connection uploads (orphaned multipart uploads).
- Snowball advice from older content is stale: Snowcone discontinued 2024-11-12, Snowball Edge closed to new customers 2025-11-07, commercial EOS 2026-12-31.
- AppFlow's first scheduled run pulls 30 days, and empty check-runs still bill $0.001 each.
- File Gateway's async flush is a durability gap: never stop a host with
CachePercentDirty > 0. - Case-study numbers are unaudited customer claims: FINRA's 6 TB / 37 billion records are AWS's 2017 report, not a current guarantee.
Comparative Verdict: DMS vs native/zero-ETL CDC vs custom Lambda loaders vs third-party tools
- Versus native or zero-ETL CDC: AWS's managed, no-pipeline path is real but its target is a warehouse, not bronze: Easygo moved Aurora PostgreSQL into Amazon Redshift automatically with Aurora zero-ETL Integration for Redshift and reported data-ingestion-related incidents down 80% (AWS case study, accessed 2026-10-11). Choose that when the consumer is Redshift. Choose DMS when you need an S3 bronze first, because that is where the documented path lives: a Full load + CDC task with
DataFormat=parquet,TimestampColumnName,CdcPath/date partitioning and optionalGlueCatalogGeneration. Native CDC wins on operational simplicity; DMS wins on landing-shape control and replayability. - Versus a custom Lambda loader: a Lambda that polls a table and PUTs to S3 must hand-roll pagination, checkpointing, throttling and retries, and then re-implement merge semantics anyway, because "Amazon S3 doesn't support primary keys, updates, or referential integrity" (AWS re:Post, 2026-02-09). DMS gives you log-based capture,
I/U/Doperation columns,IncludeOpForFullLoadparity, CDC batching (CdcMaxBatchInterval/CdcMinFileSize), date partitioning and Athena-based validation out of the box. Verdict: a Lambda loader is defensible for one small, low-change table pulled on a schedule; for anything with CDC it is a reimplementation of DMS with worse restart behaviour. Reserve Lambda for the glue around landing: event fan-out, manifest checks, Step Functions steps: not for the capture itself. - Versus third-party ETL/replication tools: Transport for NSW ran 400+ ingestion workflows on a licensed third-party ETL platform and cut annual data-integration costs by ~80% while taking new jobs from "several months" to "Less than 3 weeks" after moving to Glue + Step Functions (AWS case study, accessed 2026-10-11). That is the shape of the third-party argument in reverse: you buy breadth of connectors and a transformation UI, and you pay in licence cost, key-person dependency and lead time. Verdict: keep a third-party tool where it is genuinely differentiated, an engine DMS does not support, or a transformation layer your team would otherwise rebuild, and move everything else onto DMS + Glue so the bill returns to usage-shaped.
- The one-sentence verdict: on this AWS lakehouse in October 2026, DMS is the default for database β bronze (full load + CDC, Parquet, deterministic keys, manifest, atomic promote), native/zero-ETL wins when the destination is a warehouse, Lambda loaders are for the orchestration around landing rather than the capture, and third-party ETL stays only where it is irreplaceable: with every path converging on the same idempotent landing contract and the same Iceberg MERGE into silver.
Key Takeaways:
- Selection is a constraint, not a preference: databases β AWS DMS; SaaS APIs β Amazon AppFlow; file trees to copy β AWS DataSync; live hybrid shares β S3 File Gateway; partner protocols β AWS Transfer Family; offline bulk β DataSync / Data Transfer Terminal / partner (Snowball Edge is existing-customers-only since 2025-11-07, EOS 2026-12-31); in-bucket reorgs β S3 Batch Operations ($0.25/job + $1/million objects).
- DMS β S3 basics: CSV by default,
DataFormat=parquetfrom DMS 3.4.7; full-load files namedLOAD<hex>, CDC files named by timestamp, one folder per source table; CDC batching for Athena viaCdcMaxBatchInterval=3600+CdcMinFileSize=64000(β₯ 64 MB target);IncludeOpForFullLoadgives full-load rows anI;TimestampColumnNamesupplies the dedup/sequencing key. - DMS S3-target hard limits: no Full LOB mode, no schema change during full load, no
BatchApply, no bucket versioning, one task per source table β bucket path, ALTERs recorded but never applied to prior records, andDO_NOTHING+ restart duplicates full-load files. S3 validation needs 3.5.0+, Parquet, runs daily at 00:00 UTC, and fails on Lake Formation-managed buckets. - AppFlow: triggers are on demand / schedule / event; the first scheduled run pulls 30 days;
IncrementalPullConfig+ offset handles source timestamp lag; 15 GB β 7.5M records per Salesforce run; soft quota 100 profiles/account; $0.001 per run (empty checks bill) + $0.02/GB. - DataSync: agent required for NFS/SMB/HDFS, agentless for same-account AWS storage pairs and S3 β other cloud in Enhanced; Basic = sequential, verifies all, 50M/25M item quotas, $0.0125/GB; Enhanced = parallel, verifies transferred only, virtually unlimited objects, $0.015/GB + $0.55/execution; all agents on a location must be online; integrity checks always run; 1 file β 1 object with POSIX metadata.
- Transfer Family: SFTP/FTPS/FTP/AS2/browser into S3 or EFS across up to 3 AZs; endpoints Public / VPC-Internet / VPC-Internal; password auth needs AD or API Gateway + Lambda; $0.30/h per protocol + $0.04/GB, workflows $0.10/GB, connectors $0.001/call + $0.40/GB; 10 multiplexed SFTP sessions/connection, 1,800 s idle timeout, rename cannot overwrite, SETSTAT unsupported.
- File Gateway: NFS v3/v4.1, SMB v2/v3; path = key, 1:1 fileβobject; SSE-S3 default with MD5 verification; one share β one bucket (unique prefixes if shared); $0.01/GB written, first 100 GB free, $125/gateway/month cap, reads free;
CachePercentDirtymust be 0 before stopping the host; versioning doubles object versions. - Idempotent landing = deterministic keys β manifest β validate β atomic promote (server-side copy, not rename) β catalog β dedupe + MERGE. A replayed CDC batch must leave silver unchanged: dedupe on (business key, max
cdc_ts) first, thenMERGE INTO β¦ WHEN MATCHED AND op='D' THEN DELETE β¦ WHEN NOT MATCHED THEN INSERT. - Cost shapes decide the bill before volume does: fixed-hour (Transfer Family $216/month/protocol, DMS instance hours/DCUs, Snowball job fees $1,800 / $3,200) versus per-GB (DataSync, AppFlow, Batch Operations, File Gateway) versus hybrid: at 1 GB/month a Transfer Family endpoint costs about $216.04, which is why Β§10's first question is always "does this bill at zero traffic?".
- The end-to-end shape: DMS full load + CDC β bronze Parquet (deterministic keys + manifest) β S3 event β SQS β Step Functions β Glue job with bookmarks β dedup β MERGE into Iceberg silver β Athena CTAS counts + weekly
VACUUMβ BI. Bronze is schema-on-read; silver is schema-on-write. - Case patterns: FINRA lands exchange files over SFTP/HTTPS, validates before anything reads them, catalogs, and processes against S3 directly (6 TB / 37 billion records a day, 600+ TB lake: AWS, 2017); Transport for NSW cut data-integration costs ~80% and new-ingestion lead time from months to under 3 weeks by replacing 400+ licensed ETL workflows with Glue + Step Functions (AWS, accessed 2026-10-11).
- October 2026 state: Firehose Glue multi-catalog hierarchy (2025-05-14) can target S3 Tables; Amazon S3 Metadata GA (2025-01-27) makes landing metadata SQL-queryable in Athena; Glue 6.0 GA (2026-08-21) with a 30% price cut, Spark 4.1 and Declarative Pipelines; Snowball Edge closed to new customers (2025-11-07) with commercial EOS 2026-12-31.