The World Runs on COBOL and C. Deal With It.
The software industry is obsessed with the next big thing. Meanwhile, the code keeping civilization running is older than some of the people calling it obsolete.
Every few months, the technology industry discovers a new programming language that will supposedly change everything.
Rust is going to replace C. Python is the language of the future. JavaScript is everywhere. Go is revolutionizing backend development. Whatever framework appeared on Hacker News last Tuesday is apparently the answer to problems we didn't even know we had.
And somewhere, in a windowless room inside a bank, a COBOL program written before its current operator was born is quietly processing billions of dollars.
It doesn't have a GitHub repository full of stars. It doesn't have a Discord community. Nobody is making breathless YouTube videos about its revolutionary architecture.
It just works.
And it has been working for decades.
Welcome to the uncomfortable reality of modern computing: the world doesn't run on whatever programming language is fashionable this week. Much of its essential infrastructure still runs on COBOL, C, and a collection of technologies the industry keeps trying to bury.
The Language That Refuses to Die
COBOL was introduced in 1959.
Let that sink in.
When COBOL first appeared, John F. Kennedy wasn't president yet. The Beatles hadn't released their first album. Humanity hadn't landed on the Moon. The Internet, as we understand it, didn't exist.
And yet, more than six decades later, COBOL remains deeply embedded in banking, insurance, government administration, and large-scale transaction processing.
Why?
Because it was designed to solve a particular class of problems, and it turned out to be exceptionally good at solving them.
COBOL was built for business data processing: records, transactions, accounting, reports, and the enormous volumes of structured information that organizations must process accurately.
It isn't glamorous.
Neither is the electrical grid.
But you notice when either one stops working.
Every few years, someone announces that COBOL is dying. Universities largely stopped teaching it as a mainstream language. Developers increasingly regard it as an archaeological curiosity.
And yet the systems remain.
Not because every organization running COBOL is technologically incompetent. Not because nobody has thought about replacing it.
But because replacing a functioning system that processes critical financial transactions is considerably more complicated than rewriting a few thousand lines of code.
Which brings us to something the technology industry desperately needs to understand.
Old Doesn't Mean Broken
The word “legacy” has become one of the most abused insults in software engineering.
Originally, it simply meant software inherited from an earlier generation.
Somewhere along the way, it became synonymous with outdated, dangerous, badly designed, and desperately in need of replacement.
But those are different things.
A system can be old and exceptionally reliable.
A system can be brand-new and catastrophically defective.
I've worked with software long enough to know that the age of a codebase tells you surprisingly little about its quality.
What matters is whether it fulfills its requirements, whether it can be maintained, whether it is secure, and whether it performs reliably under real-world conditions.
A forty-year-old COBOL system that correctly processes transactions every day is not automatically inferior to a shiny new microservices architecture running on Kubernetes.
Especially if the replacement requires seventeen containers, six message queues, three orchestration layers, and a distributed tracing system just to figure out why a payment disappeared.
Complexity is not sophistication.
Sometimes complexity is just complexity.
And the fact that you can deploy something across forty servers doesn't necessarily mean you should.
Then There's C
If COBOL is the aging accountant who quietly keeps the books balanced, C is the mechanic who built the machinery everyone else depends on.
Introduced in the early 1970s, C remains foundational to modern computing.
Operating systems, embedded devices, networking equipment, databases, language runtimes, and enormous amounts of infrastructure rely on C or systems built using it.
Linux is predominantly written in C, although Rust has begun making inroads. The CPython interpreter, the standard implementation of Python, is primarily written in C. SQLite, one of the most widely deployed database engines in existence, is written in C.
Think about that for a moment.
Someone writes a Python application and proudly announces that they're using a modern language instead of ancient C.
Congratulations.
There's a very good chance that C is doing much of the heavy lifting underneath.
This isn't a criticism of Python. It's an excellent language for many applications, especially automation, data science, and artificial intelligence.
It's simply a reminder that abstraction doesn't eliminate the underlying machinery.
It hides it.
And hiding something doesn't make it disappear.
Rust Isn't the Enemy
Before the Rust enthusiasts start sharpening their pitchforks, let's establish something.
Rust is a genuinely impressive language.
Its approach to memory safety addresses real problems that have plagued C and C++ software for decades. Buffer overflows, use-after-free vulnerabilities, and other memory-related defects are not imaginary concerns invented by language evangelists.
They're serious engineering problems.
Rust offers meaningful advantages in applications where those risks matter.
But recognizing those advantages doesn't require pretending that every existing C program should immediately be rewritten.
A programming language is a tool.
And engineering is about selecting the appropriate tool for the problem, not joining a religious movement devoted to one particular hammer.
There are legitimate reasons to migrate systems to newer languages. Security, maintainability, staffing, performance, integration requirements, and changing business needs can all justify replacement.
But “this language is old” isn't an engineering argument.
It's a date on a calendar.
The Rewrite Fantasy
One of the most persistent fantasies in software development is that rewriting an existing application in a modern language will automatically produce a better application.
Sometimes it does.
Sometimes it produces an extraordinarily expensive lesson in why the original application was more complicated than anyone realized.
Consider a banking system developed over several decades.
Its source code contains business rules, regulatory requirements, exceptional cases, historical compromises, and operational knowledge accumulated through years of actual use.
Some of those rules are documented.
Others exist only in the code.
And some are there because something went spectacularly wrong in 1987, and the people who fixed it retired twenty years ago.
Now imagine a team of enthusiastic developers announcing that they're going to replace the whole thing with a modern architecture.
They examine the documentation.
They interview the users.
They study the database.
They write beautiful, modular, thoroughly tested code.
And then they discover that the old system handled a particular transaction differently on the last business day of February during leap years because of a regulatory exception nobody remembered.
The old program knew.
The new one didn't.
When you replace an old system, you're not merely replacing its code. You're replacing decades of accumulated institutional knowledge.
That knowledge has to go somewhere.
And if you don't know what it is, you can't reliably reproduce it.
This doesn't mean legacy systems should never be replaced.
It means that replacement requires engineering discipline, careful analysis, extensive testing, and an understanding of the business far deeper than “we should use something modern.”
The Economics of Boring
There's another reason old systems survive that developers sometimes dislike discussing.
Money.
A functioning system represents an investment that has already been made.
Replacing it requires new development, migration, testing, training, infrastructure, and operational support.
It also introduces risk.
If a bank's existing transaction processing system works reliably, management has to ask a very reasonable question:
What exactly are we buying with this replacement?
Lower operating costs?
Better security?
Easier maintenance?
Improved integration?
Reduced dependence on a shrinking pool of specialists?
Those can all be excellent reasons.
But if the answer is merely “the new system will use a more modern programming language,” the business case is rather thin.
Technology exists to serve a purpose.
It isn't supposed to be an expensive fashion accessory.
And yes, maintaining old systems has costs of its own. Aging hardware, expensive specialist skills, outdated interfaces, and security limitations can make continued operation increasingly difficult.
The correct decision requires comparing those costs and risks against the costs and risks of modernization.
Not comparing the release dates of two programming languages.
The Survivorship Paradox
Here's something worth considering.
A program that has been running in production for forty years has survived forty years of changing requirements, hardware transitions, operational incidents, and business evolution.
That doesn't prove the code is beautiful.
It doesn't prove the architecture is ideal.
And it certainly doesn't prove the system is secure.
But it does suggest that the system has provided enough value for someone to keep maintaining it.
Software doesn't survive for decades merely because nobody noticed it was there.
At least, not software responsible for essential operations.
It survives because replacing it is difficult, because its behavior matters, and because the organization continues to depend on what it does.
Meanwhile, entire generations of supposedly revolutionary frameworks have appeared, peaked, declined, and disappeared.
Remember when every application absolutely needed XML configuration files?
When everything had to be service-oriented?
When microservices became the universal answer, including for applications that could comfortably run on a single server?
The fashions change.
The transactions still need processing.
And the payroll still needs to run on Friday.
The Actual Future of Software
None of this means COBOL and C will dominate computing forever.
Technology evolves.
New systems increasingly use languages designed around modern security expectations, development practices, and hardware capabilities.
Rust will continue finding applications where memory safety matters. Python will remain important in data science and AI. Go, C#, Java, and other languages will continue serving enormous numbers of production workloads.
COBOL systems will be modernized, integrated, gradually replaced, or occasionally retired.
That's how engineering should work.
Evolution driven by requirements, not fashion.
The real lesson isn't that old languages are inherently better than new ones.
It's that software engineering is not a popularity contest.
The best language is the one that solves the problem effectively, safely, maintainably, and economically within the constraints of the environment.
Sometimes that's Rust.
Sometimes that's Python.
Sometimes that's C#.
And sometimes it's a COBOL program whose original author has been retired longer than its newest maintainer has been alive.
The Failure Was Designed
The technology industry has developed an unfortunate habit of confusing novelty with progress.
We celebrate the announcement of new tools while treating the continued operation of old ones as an embarrassment.
We call systems “legacy” with a sneer, forgetting that longevity is something most engineering disciplines aspire to achieve.
A bridge that remains useful for a century is an accomplishment.
A building that survives generations is admired.
A machine that operates reliably for fifty years is considered a triumph of engineering.
But software that does the same thing?
Apparently, it's technical debt.
There is something profoundly absurd about that.
Of course, old software can be dangerous. It can be brittle, insecure, expensive, and nearly impossible to maintain. Those are legitimate problems that deserve legitimate solutions.
But its age is not the problem.
Its actual deficiencies are.
And perhaps we'd make better engineering decisions if we stopped asking whether a technology is fashionable and started asking whether it works.
Because while the industry debates which language will define the future, COBOL is still processing transactions, C is still powering infrastructure, and SQL is still answering questions that somebody's business depends on.
The world doesn't run exclusively on COBOL and C. It never did.
But an astonishing amount of the machinery beneath our modern digital lives still depends on technologies that were old before today's hottest frameworks were conceived.
And tomorrow morning, when the banks open, the servers start processing, and the transactions begin flowing, those old programs will be there.
Quietly doing their jobs.
Without a keynote presentation.
Without a rebranding campaign.
And without asking anyone to smash that subscribe button.
The failure was designed. The software, fortunately, was engineered.

Comments
Post a Comment