Three different people need the same evaluation. A CTO inheriting an app from an agency that’s rolling off. A buyer doing technical due diligence on a product acquisition. A founder deciding whether their stalled codebase needs a rescue or a rewrite. The question under all three is identical: what does it actually cost to live with this code?
The evaluation that answers it is a week or two of reading (our version is a one-week decision sprint, two engineers), and the reading list matters more than the reader’s brilliance. This is the order we use, refined inside an eleven-month engagement at Domestika and every codebase since. Each step exists because we’ve watched the thing it catches stall a team.
Start with the deploy pipeline, not the code
How code reaches production tells you more per minute of reading than anything else in the repo. How long does a deploy take, and how often does one happen? Are there manual steps, and who knows them? What happens when a deploy goes wrong, and when did that last happen? A team that deploys in minutes, often, with automatic rollback, can recover from almost anything else you’ll find. A team that deploys monthly, by hand, with a person named in the runbook, is one resignation away from not being able to ship at all.
This is also where hidden complexity surfaces first. At Domestika, the deploy carried a JavaScript build tax charged on every release whether it touched JavaScript or not. You could see the problem in the pipeline before you could name it in the code.
Read the test suite like a skeptic
Coverage percentage is the most gameable number in software, so don’t write it down yet. Run the suite and time it, because suite duration is a tax on every future change. Then read actual assertions in the areas that matter, and ask of each: if this behavior broke, would this test notice? Thirteen years of accumulation gave Domestika plenty of tests that were green, plentiful, and guarding nothing, and a suite like that is worse than a missing one, because it sells confidence nobody should buy.
The practical output is one sentence you must be able to write honestly: “if the suite is green, the following things are known to work.” If that sentence comes out empty, every estimate for working on this codebase doubles.
Do the git archaeology
The repository’s history answers questions the code can’t. Who wrote the load-bearing parts, and do they still work here? Where does change concentrate (the churn hotspots are where you’ll live), and which files do people clearly avoid? When knowledge left with a person, the history shows the crater: a subsystem nobody has meaningfully touched since one author’s last commit. That crater is a cost line in your evaluation, whether you’re buying the company or just the maintenance burden.
Count the ways of doing one thing
Pick three concerns every Rails app has (rendering views, authorization, calling external services) and count the distinct patterns in use for each. One is healthy. Two means a migration is in progress; find out if it’s still moving or just stopped halfway. Three or more is the four-architectures-pretending-to-be-one-app smell we walked into at Domestika, and it predicts your onboarding cost, your bug rate at the seams, and the size of the eventual cleanup, because every parallel pattern is a dialect somebody has to keep speaking.
While counting, note what’s dead. Legacy apps accumulate code that nothing calls, and abandoned half-features that look exactly like live ones. Note the volume of can’t-tell-if-this-is-real code; it goes on the list too.
Check what the dependencies are committed to
The Rails and Ruby versions tell you the upgrade debt outright, and end-of-life versions are a security liability with a clock on it. The subtler read is the gem list: how many dependencies are abandoned, and how load-bearing are they? A core gem with no maintainer is a fork you haven’t agreed to adopt yet. The same applies to internal libraries: Domestika carried homegrown frameworks that reinvented what Rails provides, and each was a dependency with a maintenance staff of zero.
If you’re the acquirer, this section grows teeth. Run brakeman and bundler-audit and read what falls out. Grep the history for committed secrets. Check the gem licenses. Find out what personal data the app stores and where the backups live, because GDPR exposure is a price adjustment, not a footnote, and so is the monthly hosting bill. And know that the next section’s best trick may be unavailable to you: pre-close, team access is restricted and answers are incentivized, which makes the artifacts you can read on your own worth even more.
Ask the team what nobody touches
One conversation question outperforms hours of reading: “which part of the system does everyone avoid, and why?” The answer is specific, and it usually arrives with a nervous laugh. Billing, the permission system, the queue that recalculates things overnight. The no-go zone is where the implicit invariants live, the rules written in nobody’s code and everybody’s memory, and it’s the first place an AI agent or a new hire will step on a mine. Write the answer down, because it’s one of the items you’ll be pricing.
What the findings add up to
Each step produces a cost, and the evaluation is just honest addition. Slow, manual deploys: infrastructure work before anything else gets safer. Dishonest tests: characterization tests around the money paths before serious changes. A knowledge crater: budget for re-learning a subsystem from its behavior. Parallel patterns: a migration to finish or formally abandon. EOL dependencies: an upgrade with a deadline attached.
What the addition tells you depends on which of the three chairs you sit in. For the acquirer it adjusts the price. For the inheriting CTO it sets the first quarter’s plan. For the founder scoping a rescue it answers the only question that matters: whether the map says kill, keep, and build, or whether the honest verdict is something bigger. We run this as the first half of every engagement’s opening sprint, and the form factor is worth copying even if you never hire anyone: a short, fixed window of reading artifacts, ending in a list you can put prices next to.