Workflow projects rarely overrun because the workflow was hard. They overrun because of the systems the workflow has to talk to.
The pattern is consistent enough to plan around. Discovery maps the process. Design produces something everyone likes. Build starts, and somewhere in week five a developer discovers that the system of record exposes no write interface, or exposes one that requires a change request to a team in another division, or that the field everybody has been calling customer status means two different things in the two systems that hold it.
None of these are technical surprises exactly. They are discovery failures with a long fuse.
Why integrations get discovered late
Process discovery is naturally organised around people and steps, and integrations are neither. A person describing their work says “then I check the customer’s status” — a single clause in a sentence. Behind it may be a mainframe screen, a nightly export, and a colleague in another team. The interview does not surface that, because from the user’s perspective it genuinely is one clause.
Integrations are also the one area where the answer can be no. Almost every process question has an answer that costs time. Integration questions can have answers that cost the design. Discovering that in week five means redesigning with the build team idle.
The integration register
The countermeasure is unglamorous: a register, built during discovery, with one row per system the process touches. Six columns, none optional.
System and owner. Not the department — the person who can approve access. If you cannot name them, that is your first finding.
Direction. Read, write, or both. Write access is where the difficulty concentrates, and it is worth separating even when the same system does both.
Interface. What actually exists today: a REST API, a database view, a file drop, a screen a human uses. “There must be an API” is not an entry.
Authentication. How you will be allowed in, and who issues the credential. On enterprise estates this is routinely the longest lead item in the entire project — not because it is hard, but because it queues.
Availability and latency. When is it up, how fast does it answer, and what are its maintenance windows. A nightly batch turns a synchronous step into an asynchronous one, and that changes the process design, not just the code.
Failure behaviour. What happens when it is down or slow. This column is the one people skip and the one that determines whether the workflow behaves sanely in production.
Design for the failure column
Every integration step needs an answer to what happens when the call does not succeed, and there are only a few sensible answers.
Retry suits transient failures, needs a bounded count and a backoff, and is only safe if the operation is idempotent — which for writes usually means the target accepts an idempotency key. Retrying a non-idempotent write is how one payment becomes three.
Park and escalate suits sustained outages: the case moves to a queue a human monitors. This requires that the queue actually be monitored, which is an operational commitment, not a design decision.
Proceed with a flag suits enrichment that is nice to have. The case continues, marked as missing data, and something downstream reconciles.
Fail the case is legitimate but should be rare and deliberate.
The wrong answer is not choosing, because the default is an unhandled exception at three in the morning and an instance stuck in a state nobody has a screen for.
Stub early, integrate late
The practice that removes most of the schedule risk: build every integration against a stub from day one, behind an interface you control.
The stub implements the same contract as the real thing and returns fixtures. The workflow can then be built, demonstrated and tested end to end while credentials are still being requested. When the real connection arrives it is a swap, and — more valuable — the difference between stub and reality is now visible as a set of failing tests rather than a vague sense that something is off.
This also protects you from the most expensive version of the problem: discovering in UAT that the integration works but returns data in a shape the process cannot use. With a stub you agreed the shape in week one, and the mismatch surfaces as a contract violation rather than a redesign.
What to tell the sponsor
Integration lead times are usually the critical path, and they are almost never on the plan, because they look like technical detail rather than schedule risk.
Put them on it. A row per integration, with the credential request date and the owner’s name, in the same status report as the build progress. It is the least interesting slide in the pack and the one that most reliably predicts whether the date holds.
The credential lead time nobody plans for
Of everything on the integration register, the single most reliable cause of a missed date is not technical difficulty. It is waiting for access.
The pattern is consistent: a request goes to a team with its own backlog, in another division, with no stake in your deadline. It requires an approval from someone on leave. The environment it grants access to is not the one you needed. Each step is a few days and there are five of them.
Three habits compress this more than any technical decision.
Request access on day one — before design is finished, before you are certain of the exact scope. A slightly wrong access request that arrives in week two beats a perfect one that arrives in week seven, because the wrong one starts the conversation and surfaces the real process.
Request every environment at once. Teams request development access, get it, build, and discover in week ten that production access is a different process with a different approver and a longer queue.
Name the human. A register row saying “IT Security” is not actionable. A row saying a specific person, with the date you asked and the date they said, is. It also makes the dependency visible in status reporting, which is the only thing that reliably moves it.
Contract-first, so the stub is not a guess
Stubbing only removes risk if the stub is faithful. A stub built from an assumption about the interface just relocates the surprise.
Get something concrete before building: an OpenAPI document, a WSDL, a sample payload, or a recorded response from a real call. Failing that, a written description agreed by the owning team — and treat it as provisional until proven.
Then write the stub against that artefact, and write tests that assert the contract rather than the behaviour: the fields present, their types, what a not-found looks like, what an error looks like. When real access finally arrives, run the same tests against the real system. The differences are your surprise list, delivered in one batch with a diff, rather than discovered one at a time in UAT.
Record real responses as fixtures
The first time you successfully call the real system, save the response. Sanitise it, commit it, and use it as the stub’s data. It is the cheapest possible upgrade in fidelity, and it means later changes to that system show up as fixture drift rather than as a production incident.
The integration that is a person
One row on the register regularly gets missed because it does not look like an integration: the step where somebody emails somebody else, and the process resumes when they reply.
It has every property of an integration — an external dependency, a latency distribution, a failure mode, and no SLA at all. It usually has the worst latency of anything in the process and the least visibility, because the work is sitting in a mailbox where no report can see it.
Put it on the register. Give it an owner, an expected turnaround, an escalation path and a timeout. It is frequently the largest single contributor to cycle time, and because it never appears in a systems diagram it survives every round of optimisation untouched.
EFTEDRA builds workflow automation on IBM Business Automation Workflow and Claude — assistant tasks and coach views that install into the processes you already run. See what we build, or try the live demo.

