What the original pipeline actually was
The original SFTP-to-Blob pipeline was implemented in a low-code drag-and-drop Azure tool, living in a separate subscription from the dashboard programme. It had been built as a proof of concept for an unrelated piece of work, was tagged as such in the resource group, and had no production runbook, monitoring, or named owner for incident response. From the dashboard programme's point of view it had been treated as a black box that already existed, which is exactly the assumption that did not survive contact with reality.
The reroute
The OneFile ingestion Azure Function had three responsibilities after the pivot:
- Connect to the source SFTP server on a schedule, on credentials that the dashboard programme owned.
- Pull the available CSV exports, parse them, and validate the records against the schema the progress engine expected.
- Land the parsed records into the progress engine's store, with the raw CSV preserved in our own Blob container as a replay and audit artefact.
The function's contract with the rest of the system (what it produces, where it produces it, and on what cadence) did not change. That is what made the rewrite contained rather than systemic.
Why I did not try to fix the original pipeline
A reasonable reader may ask why I did not try to take ownership of the upstream PoC pipeline and harden it for production rather than rerouting around it. The honest answer is boundary cost. Promoting a low-code drag-and-drop pipeline in a different Azure subscription, owned organisationally by a different team, with no current runbook, into a production dependency the dashboard programme could rely on, in two weeks, was not a credible commitment. Building a small, owned, testable .NET path to the same data was. Boundary cost is one of the variables I weigh hardest under time pressure, and it pointed clearly in one direction.
The rollback plan
The rollback plan was straightforward: if the SFTP reroute hit a blocker we had not foreseen, the original ingestion code path was preserved on a feature branch and could be redeployed against the upstream PoC pipeline within a deployment cycle. We did not need to use it. It existed because in a deadline pivot the cost of preparing the rollback is small and the cost of needing one and not having one is enormous.
What I would do differently
The change I would make to my own process is structural, not technical. In the first two weeks of any engagement that includes external data feeds, I now run a deliberate "trace the bytes" exercise: pick one record, follow it from the source system through every infrastructure hop until it appears in the consuming system, and write down who owns each hop and what the production status of each hop is. That exercise would have surfaced the upstream PoC pipeline in week two of this engagement, not week thirteen. The pivot itself was the right call once the problem had been found. The cost is in finding the problem late.