Book a 30-minute audit

Case studies

Four weeks
somebody got back.

Every engagement starts the same way — one process, followed end to end, counted in hours. What follows is what happened next in four of them: what the week looked like before, what got built, what changed, and what went wrong on the way.

Client names and identifying details are withheld. Sectors, sizes, mechanics and figures are representative of real engagements rather than transcribed from any single one.

Freight forwarding · 40 staff · Cluj

Four hours every Monday,
matching lines by eye.

Live in
19 days
Pipelines
2
Hours back
17 / month

The week before

Every Monday morning one person opened the previous week's bank statement beside the invoice ledger and matched them line by line. Roughly 300 movements a week: most matched cleanly on amount and reference, a stubborn thirty did not — partial payments, two invoices settled in one transfer, references typed by a human at the other end.

The four hours were not the real cost. The real cost was that nobody knew which invoices were actually unpaid until Monday afternoon, so the chasing always started three days late.

What we built

Two pipelines, deliberately separate. The first pulls the statement daily, normalises the reference field, and matches on amount plus reference plus a date window. Anything it matches with full confidence is written straight to the ledger and never seen by a person.

The second handles everything the first would not touch. It groups candidate matches — one payment against several invoices, one invoice against several payments — and puts them in a single review queue with the evidence attached. A person confirms or rejects; the confirmation writes back.

  • daily statement pull · reference normalisation · amount and date window matching
  • a review queue for the ambiguous cases, with evidence attached to each
  • a Friday summary of what is still unpaid, before the weekend rather than after it

What changed

About four in five movements now match without anyone looking. The Monday session became a twenty-minute pass over the queue, and unpaid invoices surface on the day they go past terms instead of the following week.

What broke

Three weeks in, the bank changed its export format and every reference arrived with a trailing space. The matcher's confidence dropped to almost nothing overnight and the queue filled up with things it should have matched on its own.

Nothing was lost — the queue is the safety net, and it did its job. But the alert we had built fired on failures, not on a match rate falling off a cliff, so it stayed quiet while the pipeline politely did the wrong thing. We added a rate alarm that day. It is now standard on everything we build.

Accounting practice · 12 accountants · ~300 client companies

The rejection
nobody owned.

Live in
26 days
Pipelines
3
Hours back
41 / month

The week before

Invoices went to ANAF SPV in batches, from several accountants, on several days, with no shared record of what had gone and what had come back. A rejection was an email in one person's inbox. If that person was with a client, it waited.

Most rejections were mundane — a malformed VAT number, a missing field, a unit of measure the schema did not recognise. Each took two minutes to fix and up to nine days to notice.

What we built

One submission path instead of twelve. Invoices are validated against the schema before they are sent, so the predictable rejections never happen. What does get submitted is tracked in one table with a state per document, and the response is written back against it.

Rejections are classified. The known ones are routed to whoever owns that client with the specific fix named in the message. The unrecognised ones go to a person who has agreed to look at them, rather than to everybody, which is the same as nobody.

  • pre-submission schema validation · one submission path · one state table
  • rejections classified and routed by client owner, with the fix named
  • a deadline watch that escalates before the filing date, not after it

What changed

Pre-validation removed most of the rejections outright, because they were format errors that never needed a round trip. What still comes back is answered the same day. Nobody has missed a filing deadline to a rejection sitting unread since it went live.

What broke

Our first version treated the schema as fixed and hard-coded the validation rules. When a field's allowed values changed, the pipeline confidently rejected valid invoices before they ever reached ANAF — worse than the problem we set out to fix, because now the failure was ours and invisible.

We rebuilt it so the rules live in a table the practice can edit without us, and so anything the validator rejects is held for a human rather than dropped. A validator you cannot correct is a bottleneck with better manners.

Staffing agency · 25 recruiters · ~60 placements a month

Six systems,
five of them updated.

Live in
22 days
Pipelines
2
Hours back
26 / month

The week before

A signed placement started a chain of manual copying: the ATS record into the HR system, an account in the scheduling tool, a payroll line, a folder in shared storage, an entry in the client's own portal. Six destinations, one person, no checklist that survived contact with a busy Friday.

The failure was never the whole chain. It was one link, usually the least visible one, discovered when somebody could not log in on their first morning.

What we built

One trigger on the signature, then a branch per destination — deliberately not a chain. Each branch succeeds or fails on its own, so a payroll API having a bad afternoon cannot stop the storage folder being created.

Every branch reports into a per-placement record showing which destinations are done. Incomplete records raise an alert with the person's start date attached, so the urgency is visible rather than implied.

  • one signature trigger · six independent branches · no shared failure point
  • a per-placement completion record, visible to whoever is on duty
  • retries where the system is merely slow, alerts where a human is needed

What changed

Onboarding stopped being a memory exercise. The chase turned from "did anyone set up the new starter" into a list that is either complete or names exactly what is missing and who it belongs to.

What broke

The client portal branch used the only integration available: a form submission. It worked until the client redesigned the page, at which point it kept reporting success while filling in nothing — the worst kind of failure, because the record said done.

We replaced it with a read-back: the branch now re-queries the portal for the record it claims to have created, and only reports success if it can find it. Where a system will not confirm what it received, that branch is marked as needing a human and honestly says so.

Direct-to-consumer retail · ~11,000 orders a month

The exceptions
were the whole job.

Live in
31 days
Pipelines
4
Hours back
63 / month

The week before

Orders flowed into the shop and out to two couriers without much trouble. The trouble was everything else: an address the courier would not accept, a stock count that went negative between payment and picking, a refund that had to be reflected in three places, a customer emailing about an order placed under a different address.

Two people spent most of their day inside those exceptions. Neither could tell you how many there were, because handling one and counting it were the same act.

What we built

We started by counting rather than automating: two weeks of tagging every exception by type, cost in minutes, and whether it was avoidable. Around three in five turned out to be one of four repeating shapes, and one of those four was caused by a validation rule the shop was not enforcing at checkout.

That one was fixed at the source, not automated. The remaining three became pipelines: address correction against the courier's own validation before dispatch, an oversell hold that reserves stock at payment rather than at picking, and a refund pipeline that writes to all three systems from a single action.

  • two weeks of measurement before a single pipeline was written
  • the largest category eliminated at checkout rather than handled downstream
  • address validation, oversell holds, and one-action refunds across three systems
  • a weekly count by exception type, so the next thing to fix is obvious

What changed

Exception handling went from most of two people's day to a morning pass by one. More usefully, the weekly count means the team now argues about which category to remove next using a number rather than an impression.

What broke

The oversell hold worked and immediately created a new problem: abandoned checkouts held stock for thirty minutes, so during a campaign the site showed items as unavailable that nobody had bought.

We had optimised one pipeline and pushed the cost into the shop. The fix was a shorter hold with a release on abandonment, but the lesson was the general one — a pipeline that makes its own numbers look good by moving the problem somewhere else is not finished, and only measuring the whole system catches it.

Let's talk

Yours probably looks
like one of these.

If any of that sounded like a week you recognise, the next step is half a day of counting rather than a proposal. Thirty minutes on a call is enough to work out whether it is worth doing at all.