← All work

Performance & scale · Enterprise · 2024

Meridian Freight

An operations dashboard that took 40 seconds to load was costing thirty dispatchers an hour a day each. The fix was four queries, not a rewrite.

  • Rails
  • PostgreSQL
  • Redis
  • Datadog
40s → 1.2s
median dashboard load time
~1 hr/day
returned to each of thirty dispatchers
3 weeks
total engagement, run inside their existing sprint process

Where they started

Meridian's internal dispatch dashboard had grown with the company from 400 shipments a month to 40,000. It still worked, but it had gotten slow enough that dispatchers kept a second browser tab open to avoid waiting for reloads. Their engineering team knew it was slow. What they didn't have was a spare person to find out why.

What was breaking

  • An n+1 query hiding behind a helpful-looking helper method

    Each of 500 rows triggered three additional queries to render a status badge. Fifteen hundred queries per page load, from one innocuous line in a view.

  • A missing index on the column everything filtered by

    Sequential scans across 1.4 million rows on every single request.

  • Counting in Ruby what the database could count

    Six summary tiles each loaded an entire collection into memory in order to call length on it.

  • No instrumentation, so none of this was visible

    Their monitoring covered uptime but not query performance. The slowdown was invisible to engineering until a human complained loudly enough.

What we changed

  1. 1

    Instrumented first, guessed never

    We added query-level tracing before changing a single line, so every subsequent fix could be measured instead of assumed. This is the step people skip, and it's why performance work so often produces no measurable result.

  2. 2

    Fixed the n+1 with eager loading

    Fifteen hundred queries became four. This one change alone took the page from 40 seconds to about six.

  3. 3

    Added the missing index, verified with EXPLAIN

    Built concurrently so there was no downtime on a 1.4 million row table in active use.

  4. 4

    Moved the aggregates into the database

    The six summary tiles became one grouped query. Six seconds became 1.2.

  5. 5

    Left the tracing in place, with alerts

    So the next performance regression pages their engineering team instead of being discovered by their dispatchers a year later.

The expensive assumption

Meridian had budgeted for a platform rebuild. Multiple quarters, a dedicated team, the whole exercise. The dashboard was slow, the codebase was old, and the conclusion looked obvious.

It was slow for four specific, findable reasons. None of them had anything to do with the age of the codebase or the framework it was written in.

This is the most common expensive mistake we see at enterprise scale: “slow” gets treated as a property of the system rather than a symptom with a cause, and the proposed fix is sized to the frustration instead of to the problem. Two days of measurement would have told them what three weeks of work eventually did.

We’d rather tell you your problem is small. It’s a better use of your money and it’s how we end up working with people again.

“We had assumed this was a rebuild. It was three weeks and four changes. I would rather have heard that a year earlier.”

[Client name], [Title], Meridian Freight

Got something that looks like this?

Thirty minutes, no pitch. We'll tell you what it would actually take.

Book a free 30-min call

Rather not book a time? Send a message instead.