12 Code Quality Signs You Can Check Without Reading Code
12 code quality signs you can check without reading code: release frequency, tests, error rates and key-person risk, plus the questions to ask your developer.

Freelance full-stack developer
- Published
- Reading time
- 14 min
In this post7
You don't need to read code to judge code quality. The most reliable code quality signs show up in your day-to-day business: how often changes ship, who finds the bugs first, and whether the whole system depends on one person. Below are 12 signs you can check with a login and a handful of questions, and what to do when several of them point the wrong way.
Full disclosure: I'm a freelance full-stack developer in Denmark who takes over and maintains existing systems. That's why there's also a section on when a messy codebase is perfectly fine.
The short answer
Use the table as a scorecard: mark every sign where your situation looks more like "Sick" than "Healthy".
| Sign | Healthy | Sick |
|---|---|---|
| 1. Releases | Small changes go live weekly or more often | Big releases a few times a year, often after hours |
| 2. Small changes | A new field or text tweak takes hours | Every small request turns into a project with a long estimate |
| 3. Recurring bugs | A fixed bug stays fixed | Old bugs come back, and one fix breaks something else |
| 4. Error monitoring | Your developer knows before your customers do | Customers are the ones reporting errors |
| 5. Key-person risk | At least two people can work in the code | Everything stops when one person is ill or leaves |
| 6. Code access | Code lives in Git under an account your company owns | Only the developer has the code, or nobody knows where it is |
| 7. Onboarding | A new developer has it running within a day | It takes weeks and needs the previous developer's help |
| 8. Change review | A colleague or automated checks look at every change | Code goes straight from one laptop to production |
| 9. Automated tests | Tests run on every change | No tests, or tests nobody runs |
| 10. Versions | Framework and language still get security fixes | Support has ended, or nobody knows which version runs |
| 11. Path to production | Staging environment and automated deployment | Files are copied by hand onto the live server |
| 12. Technical debt | Debt is named and paid down regularly | Either everything is supposedly fine, or it all needs a rewrite |
My reading: zero to two marks is normal for a system that has been in use for a while. Three to five means someone should look at the code in the coming months. Six or more, or any mark on signs 5, 6 or 10, means act now, because those three can turn into an emergency overnight.
The signs follow from how a system is built and run, which I cover in my guide to the software development process from idea to production.
Signs you can spot without opening the code
The first four signs need no technical background. You'll find them in your inbox, on your invoices and in customer complaints.
1. Changes ship often and without drama
In a healthy codebase, a release is a non-event: small changes go live during the week and nobody holds their breath. In a sick one, changes pile up into big releases a few times a year, scheduled for evenings or weekends and followed by firefighting.
DORA, a research program that studies how software teams deliver, tracks metrics such as how often teams deploy and how often a deployment needs an immediate fix. Its finding is that speed and stability aren't a trade-off: top performers do well across all of the metrics, while low performers do poorly on all of them. Small, frequent deliveries are also the core idea behind agile, which I compare with the traditional approach in agile vs waterfall.
How to check: Ask when something last went live and how many releases happened in the past month. A system that rarely changes doesn't need weekly releases, but a finished change should be able to go out quickly.
2. Small changes cost small money
A new field on a signup form, a tweak to an email template or an extra column in a CSV export should take hours, not weeks. When even small requests turn into projects, it's usually because the code is tangled, so changing one thing means changing ten others.
Not everything that looks small is small. That new field might have to flow into invoices, permissions and your Stripe or Xero integration. The tell is in the explanation: a healthy answer names what's affected, a sick one is "it's more complicated than it looks", every single time.
How to check: Pull up your last five small requests and compare each estimate with how long it actually took to go live. If estimates keep doubling, that's a sign.
3. Fixed bugs stay fixed
Once a bug is fixed, it should stay gone. In a sick codebase the same bug reappears a few months later, or fixing one thing breaks something unrelated. Developers call this a regression, and the usual cause is missing automated tests (more on that under sign 9).
How to check: Look through your support inbox or task tracker. Do the same bugs show up twice? Does every release trigger a fresh wave of "X doesn't work anymore"?
4. Errors are caught before your customers notice
No system is bug-free. The difference is whether the bugs are known. In a healthy setup, the application reports errors to a monitoring tool such as Sentry or Flare, and uptime monitoring checks that the site responds at all. Your developer gets alerted and often fixes the problem before anyone calls. Error reports can contain personal data, so in the EU, check where the tool stores them.
In a sick setup, your customers tell you about errors, and nobody knows how many actually happen.
How to check: Ask how many errors the system logs per week and who gets notified. A healthy answer is a number and a name. "I'm not sure" is an answer too.
Signs in how the work is organized
The next four signs are about people and access. In my view they matter most, because they decide whether you can switch developers, get help in a crisis and keep building without starting over.
5. More than one person can work in the code
Developers talk about the bus factor: how many people would have to disappear before the project grinds to a halt? If the answer is one, that's your biggest risk, however good the code is. A holiday, an illness or a resignation can freeze everything, including the fix for a critical bug.
That applies when you work with a freelancer like me too. I'm one person, which is exactly why the code should sit in your account from day one and be documented well enough for another developer to take over.
How to check: Ask who could fix a critical bug if your developer were away for a month. With repository access, you can also count the different names in the past year's history.
6. You own the code and can see its history
Your code should live in version control (Git) on a service like GitHub, GitLab or Bitbucket, under an organization your company owns. Developers get access as users and can be removed again. The history shows who changed what, and when.
The sick version is code that only exists on the developer's laptop or server, an account in the developer's personal name, or nobody being sure where the latest version is. If your developer or agency is in another country, sort this out early, because recovering code across borders after a falling-out can be slow.
How to check: Ask for read access and look at the last 20 changes. You don't need to understand the code, but messages like "fix rounding in invoice export" tell you far more than "fix" or "wip". If you can't get access at all, treat it as a red flag.
7. A new developer can get started in a day
A healthy codebase has a README file (a guide at the root of the project) explaining how to run the system locally, what it depends on and how it gets deployed. A new developer can have it running on their own machine within a day.
Code that follows a mainstream framework and its conventions is also easier to hand over, because a new developer recognizes the structure. It's one reason Laravel is my default for web apps.
How to check: Ask how long it takes a new developer to get the project running. A healthy answer is measured in hours. A sick answer sounds like "it's a bit fiddly, but I can help them".
8. Changes get checked before they go live
On many teams, every change goes through a pull request that a colleague reads before it's merged. Automated tools check code style and common mistakes too, such as PHPStan for PHP and ESLint for JavaScript. In a sick codebase, changes go straight from one laptop to production without anyone, or anything, looking at them.
To be honest, a solo freelancer doesn't always have a colleague to review their work. Then automated checks and tests carry more of the load, and for large changes it can be worth paying a second developer to look.
How to check: Ask what happens between a change being finished and it going live. With GitHub access, you can see whether there are pull requests with green checkmarks from the automated checks.
Questions that reveal what's under the hood
The last four signs sit inside the codebase. You can't see them yourself, but each comes with a direct question, and you can judge whether the answer is specific or evasive.
9. Automated tests run on every change
Automated tests are code that checks the code: that a customer can log in, that an invoice adds up, that a booking can't be made twice. They run automatically on every change, and if a test fails, the change doesn't go live.
The number of tests says little on its own, and 100% test coverage isn't the goal. The workflows that make you money should be covered. I explain why this pays off even in small projects in how automated testing saves money.
How to check: Ask which of your most important workflows are covered by tests and what happens when a test fails. The healthy answer is "then the change doesn't ship".
10. Your framework and language still get security fixes
Frameworks and programming languages have expiry dates. Laravel provides security fixes for 2 years per major version, and according to Laravel's support policy, Laravel 12 loses them on February 24, 2027. PHP versions get 4 years of support in total, and security support for PHP 8.2 ended on December 31, 2026.
When support ends, the system doesn't stop working. It just stops getting patched, so the next publicly known vulnerability won't be fixed in your version. If the system handles personal data of people in the EU, it's also a GDPR question: Article 32 requires security appropriate to the risk, taking current technology into account, and in my reading (not legal advice) unsupported software is hard to defend. For the cost of waiting and how to update safely, see why you should keep software dependencies updated.
How to check: Ask which framework and language versions the system runs and when support ends. You can verify the answer yourself on the official pages.
11. There's a staging environment and a fixed path to production
A staging environment is a copy of the system where changes are tried out before they go live. Deployment itself should be automated with a tool such as GitHub Actions or Laravel Forge, so it happens the same way every time and can be rolled back.
The sick version is files copied by hand onto the live server, or changes made directly in production, with no clean way back when something breaks.
How to check: Ask how a change gets from the developer's machine to the live server, and how a bad release is rolled back. Bonus points if you can try new features in staging yourself.
12. Technical debt is named and paid down
Technical debt means the shortcuts taken to deliver faster, which you pay back later with interest in the form of slower changes. Every system carries some. In a healthy codebase, your developer can name the two or three biggest pieces of debt, and some time goes into cleanup on a regular basis.
The sick signs are the two extremes: either everything is supposedly fine because nobody looks, or it's all so bad it has to be rewritten from scratch. For how to talk about this as a manager, see technical debt explained for business leaders.
How to check: Ask which three things in the code your developer would most like to clean up, and what it costs to leave them.
When a messy codebase is perfectly fine
These 12 signs measure how a system behaves, not whether the code is pretty. Code a developer calls ugly can still work well and be cheap to change. And sometimes several sick signs are a sensible choice:
- A prototype or MVP built to test an idea, where speed beats tidiness. Signs 5, 6 and 10 still apply, and if the idea works, cleanup belongs in the next budget.
- A stable system that rarely changes. Signs 1 to 3 matter less. Sign 10 still matters if the system is online and handles personal data.
- A system you'll replace within a year. Skip the cleanup. Keep it patched and backed up, make sure you can get your data out, and put the budget into the replacement.
You also don't always need an outside developer like me. If you have an in-house team, ask them the questions below first. It's cheaper than an external review, and a good team will be glad to answer. On a hosted platform like Shopify with no custom code, watch the vendor's updates rather than a codebase.
Next steps: run a one-hour health check
Book an hour with your developer, ask the questions below and write the answers down. Send them in advance so there's time to look up numbers and versions.
Questions for your code health check
- When did something last go live, and how often does that happen?
- How many errors does the system log per week, and who gets notified?
- Who could fix a critical bug if you were away for a month?
- Can I get read access to the code under an account our company owns?
- How long does it take a new developer to get the project running?
- What happens between a change being finished and it going live?
- Which workflows are covered by automated tests?
- Which framework and language versions do we run, and when does support end?
- How do we roll back if a release goes wrong?
- What are the three biggest pieces of technical debt?
Specific answers usually mean a healthy codebase. Vague answers, or none at all, are a sign in itself, and an independent review can give you a picture to base decisions on. My page on maintenance and ongoing development of existing systems explains how I take over code: you deal with me directly, and the code stays in your account.
Frequently asked questions
Can you measure code quality with a tool?
Partly. Tools like SonarQube, PHPStan and ESLint flag complex code, duplication and common bugs, and they give you numbers. Those numbers say nothing about whether the system fits your business or whether one person holds all the knowledge. Use the tools alongside the 12 signs, not instead of them, and ask your developer what the numbers mean for you.
How do I ask my developer without sounding like I don't trust them?
Be straightforward: you want to understand the risk in a system your business depends on. A good developer is used to these questions and will answer them willingly, because the answers also document the work they've done. If your developer gets defensive or vague, make a note of it.
Does a sick codebase need to be rewritten from scratch?
Rarely. Rewrites usually take longer than planned, and the old system has to keep running in the meantime. Cleaning up piece by piece is often cheaper: security, access and tests for the key workflows first, then the parts that change most often. A full rewrite makes most sense when the technology is abandoned or the business has changed so much that the system solves a different problem.
How long does a code audit take?
It depends on the size of the system, but a first audit of a typical web app can often be done in one to a few days of work. It covers versions, tests, security, access and the biggest risks. A deeper review with a cleanup plan takes longer. Ask for a fixed price on the first audit so you know the cost upfront.
Do these signs apply to AI-generated code?
Yes. AI tools can produce a lot of code quickly, but these signs are about how code gets tested, released, monitored and handed over, and AI doesn't solve that on its own. Apps built fast with tools like Lovable or Bolt can easily lack tests, error monitoring and a fixed path to production. Run through the same 12 signs regardless of who, or what, wrote the code.