What Consulting Actually Delivers: Real Numbers from Real Engagements
The Problem With Most Case Studies
Every consulting firm has case studies. They follow a predictable format: client logo, a quote from the CTO about how transformative the experience was, and a vague claim about “significant performance improvements” or “modernizing the codebase.”
None of that helps you make a decision.
What you actually need to know: What was broken? How long did it take to fix? What did it cost? What did the numbers look like before and after? That’s the only information that lets you assess whether outside help is worth it — and what to expect if you bring someone in.
The three engagements below are real. Companies are anonymized. Numbers are not.
“They Were Spending $8,000/Month on Infrastructure for an App With 400 Active Users”
A SaaS company came to me because their AWS bill had been climbing for six months with no clear explanation. They’d already scaled up their RDS instance once. The team was convinced they needed to move to a larger database tier.
The situation: P95 response time was running around 5,400ms under normal load — not peak, just regular weekday traffic. Auto-scaling was triggering constantly, inflating their EC2 spend. The application had grown organically over four years and nobody had done a systematic performance review.
What I actually found: The database tier wasn’t the problem. A handful of high-traffic endpoints were doing full-table scans on tables with hundreds of thousands of rows. There were N+1 queries throughout the most-used views that nobody had caught because the development database had toy data in it. Three specific queries were running without indexes on the columns being filtered.
The work: Two weeks. Query profiling with rack-mini-profiler, a Bullet gem audit to surface every N+1 in the codebase, index analysis on the slow queries, and targeted ActiveRecord refactors. No architectural changes. No migration to a different database. No infrastructure work.
The numbers:
| Metric | Before | After |
|---|---|---|
| P95 response time | 5,400ms | 480ms |
| Monthly AWS spend | $8,100 | $3,200 |
| Auto-scaling events | Daily | Eliminated |
They didn’t need a bigger database. They needed someone to read the query logs.
“The Previous Senior Dev Gave Two Weeks’ Notice the Day After Their First Production Incident”
A seven-year-old Rails app. The founding developer had left two years earlier. The replacement senior dev lasted four months before walking out. The owner was running the business on infrastructure nobody fully understood, deploying with their fingers crossed.
The situation: Rails 4.2, Ruby 2.3 — both end-of-life for years. Near-zero test coverage. Gem lock hell: half a dozen gems pinned to ancient versions because upgrading any one of them broke something else. Deploy failures averaging three per month, each one requiring manual intervention. The owner had tried to hire twice; both candidates declined after the code review.
What I actually found: The codebase wasn’t as bad as the surface suggested. The core business logic was sound — it had just accumulated years of deferred maintenance. The deploy failures were caused by two specific gems that had version conflicts nobody had resolved. The hiring problem was entirely fixable: the code was scary to look at, but not architecturally broken.
The work: Twelve weeks. The first two weeks established a test coverage baseline and documented the deploy failures. Rails upgrade proceeded in steps: 4.2 → 5.0 → 5.2 → 6.1, with Ruby upgraded alongside (2.3 → 2.7 → 3.0) and gems updated at each step to avoid accumulating conflicts. CI pipeline configured. Deploy process stabilized and documented.
The numbers:
| Metric | Before | After |
|---|---|---|
| Test coverage | 0% | 47% |
| Deploy failures | ~3/month | 0 in 90 days post-engagement |
| Rails version | 4.2 (EOL) | 6.1 |
| Ruby version | 2.3 (EOL) | 3.0 |
| Time to hire | Failed twice | 2 mid-level devs hired within 60 days |
The app didn’t need a rewrite. It needed someone to do the unglamorous work of upgrading it one step at a time.
“They’d Already Spent $140,000 on a Rewrite That Was Eight Months In and Had Nothing in Production”
This one is the most common story I hear, and the most expensive.
A marketplace company had outgrown their Rails 5 app — or thought they had. They hired an agency to rebuild it in a more modern stack. Eight months and $140,000 later, the agency had delivered a half-finished system that couldn’t handle the core business workflows. The agency was unresponsive. The original app was still running but unmaintained. The team was paralyzed.
The situation: Two codebases, neither production-ready for the full feature set. The rewrite had implemented roughly 60% of the original functionality — the straightforward parts. The complex business rules that made the app actually work for their customers hadn’t been touched. Completing the rewrite would require at minimum another four to six months of work.
What I actually found: The original Rails 5 app was in better shape than the team believed. It had some real problems — outdated dependencies, performance issues on a few key queries, some architectural cruft — but it was not broken. The rewrite had been initiated based on a feeling that the app was too old to work on, not on a concrete assessment of what was actually wrong with it.
The work: Eight weeks. The first three weeks were pure stabilization of the production app: dependency updates, the worst performance issues patched, deployment process documented. Weeks four through eight produced a phased modernization roadmap — a concrete plan for addressing the real problems with the existing codebase without abandoning it.
The numbers:
| Metric | Detail |
|---|---|
| Engagement length | 8 weeks |
| Production app stabilized | Within 3 weeks |
| Additional rewrite cost (estimated) | $180,000–$220,000 to complete |
| Rewrite abandoned | Yes — phased modernization approved instead |
| Estimated future cost avoided | $180,000–$220,000 |
Note: The $180,000–$220,000 figure is an estimate based on the scope of remaining work and comparable agency rates — not a documented spend. The point is directional: finishing the rewrite would have cost more than the original app was worth.
The rewrite hadn’t failed because the team made a bad decision. It failed because nobody stopped to ask what was actually wrong with the existing app before deciding the answer was “replace it.”
What These Have in Common
Three different problems, three different scopes, but the same underlying structure: defined work, measurable goals set before anything started, and an end date.
No open-ended retainers. No scope that expanded to fill available budget. No dependency on the client continuing to pay to keep things running.
If you’re trying to decide whether outside help makes sense for your situation, the question isn’t “can we afford it?” It’s “do we know what we’re trying to fix, and can we measure whether it’s fixed?” If the answer to both is yes, the engagement has a shape. If it doesn’t, it’s worth getting there before signing anything.
Get in touch if you want to talk through what your situation actually looks like.