Back to all posts
Approval Workflows Are Killing Your Speed to Market

Approval Workflows Are Killing Your Speed to Market

Mergate Team
automation workflows productivity custom-software

“I just need a signature.”

Five words that can stop a million-dollar deal in its tracks. Five words that represent hours, days, sometimes weeks of waiting while documents sit in inboxes, approvers travel, and opportunities cool off.

Approval workflows are necessary. Approval bottlenecks are not.

The Hidden Cost of “Waiting for Approval”

Let’s trace a typical purchase order through a mid-sized company:

  1. Day 1: Employee submits PO request
  2. Day 2: Request sits in manager’s inbox (they’re in meetings all day)
  3. Day 3: Manager approves, forwards to department head
  4. Day 4: Department head is traveling, doesn’t see it
  5. Day 5: Department head approves, forwards to finance
  6. Day 6: Finance has questions, emails back to originator
  7. Day 7-8: Clarifications exchanged
  8. Day 9: Finance approves
  9. Day 10: PO finally issued

Ten days for a purchase order. Meanwhile:

  • The vendor’s price quote expired
  • A competitor who moved faster got the inventory
  • The project depending on this purchase is now delayed
  • Three people spent time chasing status updates

Multiply this by every approval in your organization: expenses, contracts, time-off requests, content sign-offs, pricing exceptions, new vendor applications…

The friction adds up to weeks of lost time across your business every single month.

Why Traditional Approvals Fail

Most approval processes were designed for a paper-based world:

  • Serial routing: Document goes from Person A to Person B to Person C, even when B and C could review simultaneously
  • Inbox dependency: Approvers have to notice the email among hundreds of others
  • No visibility: Requesters have no idea where their request is stuck
  • All-or-nothing: A $50 expense gets the same process as a $50,000 purchase
  • No escalation: If someone’s on vacation, the request just… waits

Email made these workflows electronic, but it didn’t make them smart.

Designing Intelligent Approval Workflows

Custom software lets us build approval systems that actually think. Here’s the difference:

defmodule ApprovalWorkflow do
  def route_purchase_request(request) do
    cond do
      # Small amounts: Auto-approve if within budget
      request.amount < 500 and within_monthly_budget?(request) ->
        auto_approve(request, reason: "Under threshold, within budget")
      
      # Medium amounts: Single approver
      request.amount < 5_000 ->
        route_to(request, request.submitter.manager)
      
      # Large amounts: Parallel approval
      request.amount < 25_000 ->
        route_parallel(request, [
          request.submitter.manager,
          department_finance_partner(request)
        ])
      
      # Major purchases: Sequential with executive
      true ->
        route_sequential(request, [
          request.submitter.manager,
          department_head(request),
          cfo()
        ])
    end
  end
end

Notice what’s happening:

  • Threshold-based routing: Small stuff doesn’t clog the system
  • Parallel approvals: Multiple reviewers can work simultaneously
  • Smart escalation: The right people, based on context
  • Automatic decisions: When rules allow, no human needed

The Power of Conditional Logic

Real business rules are more nuanced than “amount > X.” Custom workflows can consider:

Who’s requesting:

defp determine_approval_path(request) do
  cond do
    # Senior employees have higher auto-approval limits
    request.submitter.tenure_years > 5 ->
      %{auto_approve_limit: 1000}
    
    # New hires need more oversight initially
    request.submitter.tenure_months < 3 ->
      %{auto_approve_limit: 100, require_manager_cc: true}
    
    true ->
      %{auto_approve_limit: 500}
  end
end

What’s being purchased:

  • Pre-approved vendors might need less scrutiny
  • Certain categories (software, travel) route to specific approvers
  • Recurring purchases might auto-approve based on history

Current context:

  • End of quarter? Tighten approvals on discretionary spending
  • Emergency situation? Fast-track critical requests
  • Approver on vacation? Automatically route to delegate

Real-Time Status: No More “Where Is My Request?”

One of the biggest frustrations with approval processes is the black hole—you submit something and have no idea what’s happening.

With Phoenix LiveView, we build approval dashboards that update in real-time:

defmodule ApprovalStatusLive do
  use Phoenix.LiveView
  
  def mount(%{"request_id" => id}, _session, socket) do
    if connected?(socket) do
      Phoenix.PubSub.subscribe(MyApp.PubSub, "request:#{id}")
    end
    
    {:ok, assign(socket, request: Approvals.get_request!(id))}
  end
  
  def handle_info({:status_updated, request}, socket) do
    {:noreply, assign(socket, request: request)}
  end
  
  def render(assigns) do
    ~H"""
    <div class="approval-tracker">
      <.step status={step_status(@request, :submitted)} label="Submitted" />
      <.step status={step_status(@request, :manager)} label="Manager Review" />
      <.step status={step_status(@request, :finance)} label="Finance Review" />
      <.step status={step_status(@request, :complete)} label="Complete" />
    </div>
    """
  end
end

Requesters see exactly where their request is, who has it, and how long it’s been there. No more chasing status. No more wondering.

Automatic Escalation: Requests Don’t Get Stuck

What happens when an approver doesn’t respond? In most systems: nothing. The request just sits there.

Smart workflows include escalation logic:

defmodule ApprovalEscalation do
  use Oban.Worker
  
  @impl Oban.Worker
  def perform(%{args: %{"request_id" => id}}) do
    request = Approvals.get_request!(id)
    
    if request.status == :pending_approval do
      hours_waiting = hours_since(request.assigned_at)
      
      cond do
        hours_waiting > 48 ->
          escalate_to_supervisor(request)
          notify_original_approver(request, :escalated)
          
        hours_waiting > 24 ->
          send_reminder(request.current_approver, request)
          
        hours_waiting > 4 ->
          send_nudge(request.current_approver, request)
      end
    end
    
    :ok
  end
end
  • 4 hours: Gentle reminder
  • 24 hours: More urgent reminder
  • 48 hours: Escalate to their supervisor

Requests never get stuck. Approvers know the clock is ticking.

Mobile Approvals: Decide Anywhere

Your executives are rarely at their desks. Traditional workflows wait for them to open their laptop and check email.

Modern approval systems meet approvers where they are:

  • Push notification with request summary
  • One-tap approve/reject for simple requests
  • Quick review interface for complex ones
  • Secure, authenticated, audit-trailed

That department head traveling for a conference? They approve the urgent PO from the taxi to the airport. Four days saved.

The Audit Trail: Compliance Without Friction

“Who approved this and when?”

With email-based approvals, answering this question means digging through inboxes and reconstructing a paper trail.

With a custom approval system, every action is logged automatically:

defmodule ApprovalAudit do
  def log_action(request, action, user, metadata \\ %{}) do
    %AuditEntry{
      request_id: request.id,
      action: action,
      user_id: user.id,
      timestamp: DateTime.utc_now(),
      ip_address: metadata[:ip],
      device: metadata[:device],
      notes: metadata[:notes]
    }
    |> Repo.insert!()
  end
end

Complete history, instantly searchable, always available for audits. Compliance becomes a byproduct, not a burden.

Before and After: Real Impact

Before smart workflows:

  • Average approval time: 5.2 days
  • Requests stuck >1 week: 23%
  • Time spent chasing status: 4 hours/week per manager
  • Compliance audit prep: 2 days

After smart workflows:

  • Average approval time: 4.2 hours
  • Requests stuck >1 week: <1%
  • Time spent chasing status: 0 (it’s self-service)
  • Compliance audit prep: 15 minutes (export the log)

Common Workflows We Automate

Almost every business has these approval bottlenecks:

Financial:

  • Purchase orders and requisitions
  • Expense reports
  • Invoice approvals
  • Budget exceptions
  • Vendor payments

HR:

  • Time-off requests
  • New hire approvals
  • Salary adjustments
  • Policy exceptions
  • Training requests

Operations:

  • Change requests
  • Quality sign-offs
  • Shipping exceptions
  • Inventory adjustments
  • Maintenance approvals

Sales:

  • Pricing exceptions
  • Contract terms
  • Credit limits
  • Discount approvals
  • Custom quotes

If people are waiting on other people to click “approve,” there’s probably a better way.

Getting Started

You don’t need to overhaul every approval process at once. We recommend:

  1. Identify your worst bottleneck: Which approval causes the most delays or frustration?

  2. Map the current process: Who approves what? What are the real rules (vs. the stated rules)?

  3. Design the ideal flow: What should happen? What can be automated?

  4. Build and measure: Deploy the new workflow, track the improvement

  5. Expand: Apply learnings to the next bottleneck

Stop Waiting, Start Moving

Every day your team spends waiting for approvals is a day your competitors might be moving faster.

The solution isn’t to eliminate approvals—oversight and control matter. The solution is to make approvals instant when they can be and fast when they can’t be.

Smart routing. Automatic escalation. Real-time visibility. Mobile access. Complete audit trails.

That’s what modern approval workflows look like.

Let’s talk about which approval bottlenecks are slowing your business down. We’ll help you design workflows that maintain control while eliminating friction.


The best approval is the one you never had to wait for—because the system was smart enough to handle it automatically while maintaining the oversight you need.

Live Demo: Real-Time Inventory

This interactive component demonstrates how we combine Phoenix LiveView for real-time updates with Svelte for smooth client-side interactions. Try it out – in a production app, these changes would sync instantly across all connected users.