Let's discuss your appHaving a SW issue?
Back to blog
TechnologyLegacy CodeRefactoringBehind the ScenesTechnology

We Inherited the Code: Worst Findings in Legacy Projects

Lukáš HusoFebruary 26, 20266 min read
We Inherited the Code: Worst Findings in Legacy Projects
Photo: John Barkiple / Unsplash

In our industry, there's a special kind of excitement. Not the pleasant kind. More like that chill running down your spine when you open a project from a previous developer and gradually realize the scale of the disaster. We call it "inheritance shock," and we've experienced it many times.

These are our most memorable findings. Names and details have been changed, but the horror is authentic.

Plaintext Passwords (and Worse)

Let's start with a classic that shouldn't surprise anyone — and yet surprises us every time. We took over an e-shop for a mid-sized company. The first thing we did was look at the database. The users table, password column. And there, beautifully readable: Password123, MyFirstPassword, admin.

No hashing. No salting. Just plain text. Thousands of user passwords that anyone with database access could read.

But the best part was yet to come. In the same project, we found a file called passwords_backup.txt in the web root directory. Publicly accessible. It contained login credentials for the database, FTP server, email account, and payment gateway. Just a convenient list in case the developer forgot their credentials. Or in case someone wanted to steal them.

Five Thousand Lines in One File

One of our favorite exhibits: a PHP file called functions.php. Five thousand two hundred lines. One function. No, you didn't misread that — the entire file was one massive function that did literally everything. It processed forms, generated HTML, sent emails, communicated with the database, calculated VAT, and in one peculiar block around line 3,400, it even checked the weather via an external API.

The function was called doStuff(). And it did a lot of stuff indeed.

The most beautiful thing about it was the nested if-else blocks going twelve levels deep. Anyone who has ever seen code indented by 48 spaces knows what I'm talking about. Reading it required horizontal scrolling like you were viewing a panoramic photograph.

SQL Injection: Open Doors for Everyone

This finding genuinely scared us. We took over a web application for managing corporate documents. Sensitive contracts, invoices, employees' personal data. And in the code:

$query = "SELECT * FROM documents WHERE id = " . $_GET['id'];

No prepared statements. No escaping. No input validation. Literally every user input was concatenated directly into SQL queries. An attacker could use the URL to extract the entire database, delete it, or create an admin account for themselves.

And this wasn't an isolated case. The entire application — dozens of files — worked the same way. It was like finding a house where the doors aren't just unlocked — there are no doors at all.

Two Thousand !important Declarations

CSS can be tricky, we'll admit that. But what we found in one project exceeded all expectations. A stylesheet of 8,000 lines with nearly 2,000 occurrences of !important.

Why? Because every new developer who worked on the project discovered that their styles didn't work (thanks to the previous developer's !important), so they added their own !important. This created an escalating specificity war where eventually every single rule needed !important just to function at all.

The best line we found in there:

.button { color: red !important; /* TODO: WHY DOESN'T THIS WORK */ }

It didn't work because twenty lines below was:

.container .button { color: blue !important; }

Version Control by Zipping and Emailing

"How do you version your code?" is a question we always ask when taking over a project. Usually we hear "Git" or at least "SVN." Once, we heard an answer that temporarily knocked us out of commission:

"We send each other zip files by email. The latest version is the one Peter sent last Thursday. Or maybe it was John on Friday. Check both."

The project had no version control system. No change history. No way to revert to a previous version. Developers were emailing files to each other and hoping they wouldn't overwrite each other's work. Spoiler: they did.

When the project was handed over, we received a folder named web_final_v2_FINAL_fixed_FINAL2_done.zip. That tells you everything you need to know.

Stack Overflow with the Author's Signature

This one is more amusing than horrifying. In one project's code, we found comments that clearly revealed their origin:

// Source: https://stackoverflow.com/questions/1234567
// answered by user xXxCoderPro2003xXx
// This might not work for all cases but it works for me
function parseDate(str) {
  return new Date(str.split('-').reverse().join('/'));
}

Of course, it didn't work for all cases. The date "31-02-2024" passed without error and created March 3rd. But more importantly — the entire project was assembled this way from copied Stack Overflow answers. Without understanding what the code does. Without adapting it to the specific context. Sometimes even including comments from the answerer explaining why it was just a quick fix and not production code.

Legacy Code Anti-Patterns
  • Plaintext passwords in the database
  • A doStuff() function with 5,000 lines
  • Direct SQL query concatenation
  • Code versions sent as zip files via email
  • 2,000 !important declarations in one CSS file
Clean Code Practices
  • Hashed and salted passwords (bcrypt/argon2)
  • Small, specialized functions (under 50 lines)
  • Prepared statements for SQL queries
  • Code versioning in Git with code reviews
  • CSS methodology (BEM, utility classes)

Why This Happens

Most of the time, there's no malicious intent behind these horrors. It's a combination of factors: low budgets ("do it as cheaply as possible"), time pressure ("we needed it yesterday"), inexperienced developers, missing code reviews, and gradual quality erosion where every shortcut creates room for the next shortcut.

Technical debt works exactly like financial debt. A small amount of debt is normal and manageable. But if you ignore the payments, interest grows exponentially. And one day you realize that instead of adding new features, you're spending all your time fighting fires in old code.

The Lesson

Behind every legacy project, there's a story. A story of pressure, constraints, and compromises. We don't judge — we know that in the real world, there isn't always room for the perfect solution.

Moral of the story: Technical debt is real debt. You can ignore it, but it won't disappear. On the contrary — it grows. And eventually, you'll have to pay it back, usually with interest. If you're building a product, invest in code quality from the start. It's cheaper than a rescue operation later. Trust us — we perform those rescue operations and we know what they cost.

Inheriting a legacy project? Audit systematically: 1) Security — passwords, SQL injection, authorization. 2) Architecture — file sizes, dependencies, duplication. 3) Infrastructure — version control, CI/CD, environments. 4) Documentation — does any exist? Do not try to fix everything at once. Prioritize by risk and refactor incrementally with each new task.

Related Articles

Progressive Web Apps vs. Native Apps in 2026
TechnologyPWATechnology

Progressive Web Apps vs. Native Apps in 2026

A detailed comparison of PWA and native apps in 2026. When to choose PWA, what are its limits, and where native development still leads.

February 24, 20267 min read
AI Revolution in Mobile App Development: Faster, Cheaper, But Not Without People
TechnologyAIApp Development

AI Revolution in Mobile App Development: Faster, Cheaper, But Not Without People

How AI is transforming app development. Why services like TvojeAplikace.cz deliver faster and at lower cost thanks to AI — and why senior developers are still essential.

February 14, 20265 min read
How to Choose the Right Technology for Your Web Application
TechnologyTechnologyWeb

How to Choose the Right Technology for Your Web Application

A guide to selecting the technology stack for your next web project. We compare React, Next.js, Vue, and other frameworks.

January 15, 20252 min read