Skip to content

Rethinking how internal requests found the right person

Request routing tree - internal task workflows

TL;DR

Diagnosis

When I took over the project, the platform already had a task module in progress. But it was missing the most important part: getting requests to the right people. Someone reporting a lost parcel doesn’t know who will handle it, and doesn’t need to. It’s enough for them to say what happened. Writing to people one by one works poorly, because the more requests there are, the more time slips away on them. So we didn’t need a nicer task list. We needed a layer that takes a request by problem type and hands it to the team that deals with it. I put it inside the platform where the order already was, so nobody had to switch to another tool.

flowchart TD
    subgraph Before["Before"]
        A1["Reporter writes to person 1"] --> A2{"Reply?"}
        A2 -->|"no"| A3["Writes to person 2, 3..."]
        A3 --> A2
        A2 -->|"yes"| A4["Someone finally picks it up"]
    end
    subgraph After["After"]
        B1["Request: problem type"] --> B2["Automatic handoff to the team"]
        B2 --> B3["The right team takes the task"]
    end

    classDef good    fill:#e6f2ea,stroke:none,color:#1f4d33,rx:14,ry:14
    classDef bad     fill:#faeaea,stroke:none,color:#5f2626,rx:14,ry:14
    classDef accent  fill:#27272a,stroke:#3f3f46,stroke-width:1px,color:#fafafa,rx:14,ry:14
    class A1,A2,A3,A4 bad
    class B1,B2 good
    class B3 accent
    style Before fill:#fdf5f5,stroke:#e0c3c3,stroke-width:1px,color:#5f2626,rx:14,ry:14
    style After fill:#f2f8f3,stroke:#c2dcc8,stroke-width:1px,color:#1f4d33,rx:14,ry:14
    linkStyle default stroke:#a8a8b3,stroke-width:1.5px

What I did

Results

#WorkflowStatus
1Lost parcelin production
2Invoice correctionin production
3Refundin production
4Shipping statusin production
5–10+other request typesin production

The problem

Why were internal requests so slow?

The company made packaging to order. Every order goes through specification, quoting, production, shipping and billing, and something can go wrong at every stage. When a parcel got lost or an invoice had an error, the person who noticed (often from customer service) wrote to one colleague after another until someone took it on. They didn’t know who to go to, because there was no system. The more requests there were, the more time this took, and nobody could see what was open and who was working on it.

Why not buy an off-the-shelf ticketing system?

Because all the work already happens in the order-handling platform. A separate tool means another login, another place to check and more data to keep in sync. The system had to be simple and work where the order is.

My role / scope

Process

Key decisions & trade-offs

flowchart LR
    O["Order view<br/>existing platform"] --> T["Task system<br/>built in"]
    Alt["Separate ticketing system"] -->|"another login, switching tools"| O

    classDef good    fill:#e6f2ea,stroke:none,color:#1f4d33,rx:14,ry:14
    classDef bad     fill:#faeaea,stroke:none,color:#5f2626,rx:14,ry:14
    classDef accent  fill:#27272a,stroke:#3f3f46,stroke-width:1px,color:#fafafa,rx:14,ry:14
    class O good
    class T accent
    class Alt bad
    linkStyle default stroke:#a8a8b3,stroke-width:1.5px

Two sketches side by side: the manager view grouped by person with an "unassigned" group at the top, and the employee view with their tasks grouped by workflow type

A reconstructed sketch. The same pool of tasks in two views, for a manager and for an employee (inspired by Notion databases and Jira and Asana boards).

How it turned out

We rolled the system out quickly, and teams started using it quickly. In the first three months there were more than 10 workflows running and ~300 tasks a month. For the first time it was also possible to measure the handling time of each process. I left before the command palette and automatic assignment were rolled out, so I only write about what we shipped while I was there.

What I took away