Logistics Data Modernisation
A watermark-based ingestion pipeline, and the operational discipline of letting the pipeline remember what the analyst no longer needs to.
Designed and implemented an incremental data ingestion pipeline using Microsoft Fabric to modernise logistics data processing for a global freight company. The solution automated ingestion of high-volume JSON shipment logs using a watermark-based state management approach, eliminating manual file selection, reducing reporting latency, and ensuring reliable, auditable data ingestion into a Delta Lake architecture.
Project scope
Developed an end-to-end incremental data ingestion pipeline that automates JSON file processing, tracks ingestion state using watermarks, stores data in Delta Lake, and delivers reliable, scalable, and auditable data for downstream analytics.
Objectives
- Automate incremental data ingestion.
- Process only new shipment files.
- Eliminate duplicate and missed records.
- Improve data reliability and auditability.
- Reduce reporting latency through automated pipelines.
Challenges
- The Post-Trigger File
- The Silent Column
- The Contaminated Table
Solution
Data pipeline architecture and workflow
- Initialize State: looked up the previous watermark timestamp to identify the exact starting point for data extraction.
- Incremental Load: filtered and extracted only newly arrived data based on the watermark, appending unique records to the master file.
- Advance Watermark: automated a query to update the watermark log with the pipeline’s trigger timestamp post-execution.
View full size (opens in a new tab)Steps involved in setting up the pipeline architecture and workflow
The whole design rests on one idea: the pipeline keeps a durable record of how far it has read, so no human has to remember which files were already processed.
1. Create the watermark log table (SQL)
Designed a SQL table to track the last processed timestamp and manage the pipeline’s incremental state.
View full size (opens in a new tab)2. Seed the baseline watermark
Executed a SQL INSERT statement to populate the initial timestamp value, establishing the
starting baseline for the incremental load.
View full size (opens in a new tab)3. Automate watermark updates
Configured an UPDATE query to execute at the end of each successful pipeline run,
advancing the timestamp to log the new state.
View full size (opens in a new tab)4. Configure the Lookup activity
Set up a Lookup activity against the watermark log table to retrieve the last successfully processed watermark timestamp. This establishes the starting point for the current pipeline run.
View full size (opens in a new tab)5. Configure the incremental data flow
Set up the core extraction logic, via a Copy or Data Flow activity, to filter the source data using the retrieved watermark timestamp. This ensures the pipeline pulls only newly arrived files and cleanly appends them to the main Delta Lake table without duplication.
View full size (opens in a new tab)6. Configure the watermark update (Notebook activity)
Set up a Notebook activity parameterised to receive the dynamic pipeline trigger time. Upon successful data ingestion, the notebook executes a script to update the watermark log table with this new timestamp, resetting the baseline for the next run.
View full size (opens in a new tab)The scenarios that test the design
The Post-Trigger File
It is 6:03 AM. The pipeline has run. At 8:47 AM, a carrier uploads a new file containing the status update David needs for his 9:00 AM report. What happens?
No, it will not be picked up by today’s pipeline. Assuming the pipeline operates on a daily morning schedule, it already completed its run at 6:03 AM. Because the pipeline is triggered by a schedule rather than by an event such as a file landing, it is currently inactive. The file will sit safely in the landing zone and will be ingested during tomorrow’s scheduled run, at 6:00 AM.
This is a real limitation, not a defect: the fix is an event-based trigger, and the trade-off is cost and run frequency against reporting freshness. Naming it explicitly is what lets the business choose.
The Silent Column
The carrier integration team adds an InsuranceValue field to all JSON files over the weekend. Monday's pipeline succeeds without error. The field is nowhere in the table.
The pipeline succeeded because it was never told to expect the field. The write matched
the existing schema and quietly dropped the rest. The recovery is to update the schema:
execute a SQL command against the destination Delta table to add the missing
InsuranceValue field, then backfill from the archived source files.
The broader lesson is that a green pipeline run is not the same as correct data. Schema drift is silent by default, which is exactly why it needs an explicit check.
View full size (opens in a new tab)A third scenario, The Contaminated Table, covers recovery once bad data has already been appended to the Delta table.