I was wiring a Flutter app to the same Strapi APIs a deployed React web app already used. Dio made the requests. The product needed a visit to go through a chain, not a single call:
Record audio → Transcribe → Identify speaker → Transcript → Get summary → Save
Three to five of those APIs fired back to back. The app felt slow. Worse, the result on Flutter sometimes did not match what React produced for the same visit.
The sequence was the product
Each step needed the one before it. You cannot identify a speaker before there is a transcription. You cannot ask for a summary before there is a transcript. You cannot save a visit that has not gone through that pipeline.
The web app was already live. It had an order. Flutter had to hit the same APIs in the same business sequence, or the two clients would disagree about what a finished visit looked like.
That is easy to say and easy to break. Once you have Dio in a Flutter widget, it is tempting to fire the next request as soon as the previous future completes, or to overlap calls that look independent. Overlapping the wrong ones is how I got mismatches.
What actually went wrong
Latency was the obvious part. A chain of three to five Strapi round trips, one after another, is a long wait if the UI sits on a spinner until the last one returns.
The hidden part was consistency. If Flutter skipped a step, reordered one, or continued after a failed call that React would have retried, the saved visit was not the same object the web app expected. Speaker labels, transcript text, and the summary could drift even when every individual request had returned 200.
I treated that as a networking problem first. It was a product-sequence problem. The live React flow was the spec.
What I changed
I tightened the calls so the chain was not waiting on work it did not need, without collapsing steps React still ran. Dio retries covered the failures that used to abort the pipeline halfway through. async/await kept the remaining order explicit instead of a pile of nested callbacks. The UI stopped pretending the whole visit was "loading" and showed where it was: transcribing, identifying the speaker, building the summary, saving.
None of that is clever. It is the difference between a Flutter client that happens to talk to Strapi and a Flutter client that implements the same visit the web app already ships.
What I would not skip next time
Concurrent Dio calls are useful when the product does not care about order. This product did. Before I parallelize anything against a live frontend, I write down that frontend's sequence and treat it as the contract: same APIs, same order, retries on the same failures, a status the user can actually read.
The chain is still record, transcribe, identify speaker, transcript, summary, save. Flutter is only done when that sequence has finished the way React already finishes it.