Before and after
| Before | After |
|---|---|
| Partners upload to an SFTP VM | Partners upload to managed SFTP backed by object storage |
| Cron at 02:00 copies and loads everything | Each file triggers ingestion within minutes |
| Late file = missed day | Late file is processed whenever it arrives |
| Bad file breaks the whole run | Bad file goes to quarantine; others load |
1. Managed SFTP endpoint
Azure — SFTP on a storage account (hierarchical namespace required) with local users per partner:
az storage account update -g rg-ingest -n stpartners --enable-sftp true
az storage account local-user create -g rg-ingest --account-name stpartners -n partnerA \
--home-directory landing/partnerA --permission-scope permissions=cw service=blob resource-name=landing \
--has-ssh-key true --ssh-authorized-key key="ssh-rsa AAAA..."
AWS — Transfer Family SFTP server with an S3 backend and per-user home directories.
Give partners write-only access to their own folder.
2. React to new files
| Platform | Mechanism |
|---|---|
| Databricks | Auto Loader with file notification mode (Event Grid / SQS set up for you) |
| Snowflake | Snowpipe with auto-ingest (Event Grid / S3 event notifications) |
| ADF / Fabric | Storage event trigger on BlobCreated |
Databricks Auto Loader example:
(spark.readStream.format("cloudFiles")
.option("cloudFiles.format", "csv")
.option("cloudFiles.useNotifications", "true")
.option("cloudFiles.schemaLocation", "/Volumes/main/ingest/_schemas/partnerA")
.option("header", "true")
.load("abfss://landing@stpartners.dfs.core.windows.net/partnerA/")
.writeStream
.option("checkpointLocation", "/Volumes/main/ingest/_checkpoints/partnerA")
.trigger(availableNow=True) # or processingTime="5 minutes" for continuous
.toTable("main.bronze.partnerA_orders"))
Snowpipe example:
CREATE PIPE raw.partner_a_pipe AUTO_INGEST = TRUE INTEGRATION = 'NOTIF_INT_PARTNERS' AS
COPY INTO raw.partner_a_orders FROM @partner_stage/partnerA/ FILE_FORMAT = (TYPE = CSV SKIP_HEADER = 1);
3. Validate every file
- Naming convention and expected extension.
- Header/schema check; row count vs. a control file or trailer record.
- Duplicate file detection (hash or filename registry).
Route failures to a quarantine/ path and notify the partner contact automatically, rather than failing the pipeline.
4. Handle "all files for the day" logic
Some downstream processing really needs a complete set. Keep ingestion per file, and run the downstream step when a completeness rule is met (all expected partners arrived, or a cut-off time passed) — not when cron fires.
5. Decommission the SFTP VM
Migrate partners one at a time: create their user, share the new host and key requirements, run both endpoints in parallel for a week, then disable the old account.
Tip
Keep the raw files (immutable, with lifecycle to cool/archive tiers). They're your replay source when a transformation bug is found later.
Checklist
- Managed SFTP with per-partner users and folders
- Event-driven ingestion with checkpoints
- Validation and quarantine with notifications
- Completeness rules for downstream jobs
- Partners migrated; old SFTP VM retired