Languages
Perl
Keeping legacy Perl alive, safe and maintainable — and migrating it off Perl when that serves you better.
Overview
Perl is a veteran, pragmatic scripting language that shaped the early internet. Through the late 1990s and 2000s it was the workhorse behind CGI web scripts, log parsing, system administration glue, report generation and a great deal of bioinformatics — earning the nickname “the duct tape of the internet” for its ability to hold disparate systems together. Its defining strengths are famously powerful, terse regular expressions, first-class text manipulation, and CPAN: one of the largest and oldest module archives of any language. Perl’s guiding motto, “there’s more than one way to do it” (TMTOWTDI), gave developers enormous freedom — and, in the wrong hands, produced code that was quick to write and painful to read.
Today the honest picture is different. Perl’s popularity has declined sharply, the talent pool is ageing and shrinking, and its “write-only” reputation — dense, clever code that resists later understanding — is partly deserved. Yet a great deal of quietly critical infrastructure still runs on Perl: billing pipelines, ETL jobs, deployment tooling, internal web applications and data-processing scripts that have worked reliably for fifteen or twenty years. That code is not going away on its own, and rewriting it wholesale is often riskier than the problem it solves.
So our work with Perl is almost entirely legacy maintenance and migration, not greenfield development. Organisations come to us because a valuable Perl system needs to be kept running safely, stabilised, secured, gradually improved, or moved to a modern language — usually Python. We do that pragmatically: we read the code that exists, understand what it actually does in production, and choose the least risky path forward. Sometimes that is careful maintenance; sometimes it is an incremental migration; only rarely is it a full rewrite, and we will tell you plainly which one your situation calls for.
Best for — Organisations with a valuable legacy Perl system that must be maintained, secured, stabilised, or migrated — handled pragmatically by senior engineers rather than forced into a risky rewrite.
Why teams choose Perl
Your legacy system stays alive and safe
The Perl that quietly runs your billing, reporting or automation keeps working — but with tests around it, its dependencies patched, and someone senior who genuinely understands it. You stop carrying an undocumented risk you cannot afford to lose.
A clear-eyed migration path, when you want one
Rather than being told to “just rewrite it”, you get an honest assessment of whether to maintain, incrementally migrate, or leave well alone — and if migration is right, a staged plan to Python that preserves behaviour and reduces risk at every step.
Risk removed from an ageing codebase
We turn tribal knowledge into documentation and tests, remove the “only one person understood this” problem, and make a fragile system safe to change — which is often more valuable than any new feature.
Why businesses choose Perl
- You have real, working Perl that matters to the business and needs experienced hands, not a junior guessing at twenty-year-old code.
- You want honesty about the trade-off between maintaining and migrating — including being told when leaving it alone is the right call.
- You need the risk taken out of an ageing, under-documented system before it fails at the worst possible moment.
- You want a migration to Python done incrementally and verifiably, by people who understand both the old code and the new target.
What we build with Perl
The capabilities this technology is genuinely strong at — and what we most often build with it.
Regular expressions and text processing
Perl’s regular expressions are among the most powerful in any language, and text manipulation is what it does best. We use that strength deliberately when maintaining parsers, log processors and data-munging scripts — and we know when a regular expression has grown too clever to maintain and should be tamed or replaced.
CPAN module archive
Perl’s vast module archive means much legacy code leans on established libraries. We audit which CPAN modules a system depends on, whether they are still maintained, and where an unmaintained or vulnerable dependency needs replacing or pinning — a common source of hidden risk in old Perl.
Legacy CGI and mod_perl web applications
A great deal of surviving Perl is web code: CGI scripts and mod_perl applications from an earlier web era. We understand these deployment models, their security pitfalls, and how to keep them running behind a modern reverse proxy — or how to lift them onto something current when that is warranted.
System administration and automation glue
Perl was the automation language of choice for a generation of sysadmins. We maintain the cron jobs, deployment scripts and ETL glue written in it, and where they have become fragile we harden them with error handling, logging and tests before touching behaviour.
Modern Perl practices where it still lives
When a Perl system will genuinely remain in service, we bring it toward modern practice — strictures, sane module structure, and object systems such as Moose or Moo where they help — so the code that stays is less “write-only” and easier for the next person to own.
DBI and database integration
Much legacy Perl talks to relational databases through DBI. We understand the drivers, the connection handling, and the SQL these systems generate — including the injection risks in older code — and we secure and stabilise that data layer whether the system stays in Perl or moves.
Use cases
Stabilising a critical legacy system
A long-running Perl pipeline or internal application that the business depends on but nobody fully understands. We document it, put tests around its real behaviour, patch its dependencies, and make it safe to operate and change.
Incremental migration to Python
Moving a Perl codebase to Python one component at a time — the old and new systems running side by side, behaviour verified against the original at each step — so the business is never exposed to a single risky cutover.
Rescuing an unowned, fragile codebase
Perl that has lost its original authors and drifted into a black box. We reverse-engineer what it does, capture that knowledge in tests and documentation, and remove the single-point-of-failure risk that comes with unowned code.
Ongoing maintenance and security patching
Keeping a Perl system healthy over time: applying security fixes, handling data-format and integration changes, and making small, well-tested improvements without disturbing the parts that reliably work.
When Perl is the right choice
- You own a valuable, working Perl system — a data pipeline, an internal web app, a fleet of automation scripts — that must keep running reliably, and you need senior people who can maintain and stabilise it rather than let it rot.
- You have a Perl codebase that has become fragile or unowned: the original authors have left, nobody fully understands it, and you need it documented, tested and made safe to change before it breaks in production.
- You want to migrate off Perl onto a modern language — most often Python — and need that done incrementally, with behaviour preserved and verified, rather than as a big-bang rewrite that risks the business.
- Wrong for: a new, greenfield project. In 2026 there is almost no case for starting fresh in Perl. Python offers a comparable scripting model, far better readability, a much larger and younger hiring pool, and a healthier ecosystem — it is the better choice for new work, and we will say so.
- Wrong for: a team hoping to hire a Perl department. The talent market has thinned to the point where staffing new Perl work is genuinely hard; if your strategy depends on recruiting Perl engineers at scale, that strategy needs rethinking, and migration is usually the honest answer.
Perl: pros and cons
Strengths
- Unmatched text processing and regular-expression handling — Perl’s original reason for existing, and still genuinely excellent for parsing, transforming and munging text and logs.
- CPAN is vast and mature: for the problems Perl was built for, a well-tested module very likely already exists, often battle-hardened over two decades.
- It is highly portable and pre-installed on virtually every Unix and Linux system, which is exactly why so much durable system-administration and glue code was written in it.
- Enormous stability: Perl 5 has prized backwards compatibility for years, so code written long ago frequently still runs unchanged — the reason so many legacy systems have survived.
Trade-offs
- A shrinking ecosystem and hiring pool. The community is ageing, fewer new modules appear, and recruiting Perl engineers is difficult and getting harder — a real business risk for any Perl-dependent system.
- Readability and maintainability are genuine problems. TMTOWTDI and terse idioms make it easy to write dense, “write-only” code that later maintainers — including the original author — struggle to follow.
- New development in Perl is hard to justify. For almost any greenfield task, Python or another modern language gives you better tooling, clearer code and an easier hiring story.
- Sparse comforts by modern standards: weaker native tooling, editor support and library momentum than mainstream languages today, so day-to-day development feels dated compared with Python or JavaScript.
Architecture
Legacy Perl systems rarely have a documented architecture — they have an accreted one, grown over years of scripts, cron jobs, shared modules and database access that made sense to someone at the time. Our first job is to reconstruct the real shape of the system as it runs in production: what the entry points are, which scripts depend on which modules, where state lives, what talks to the database, and which parts are genuinely load-bearing versus long-dead code nobody dares delete. That map is the foundation for every decision that follows.
With the true architecture understood, we choose the least risky path. Where a system will stay in Perl, we introduce clear boundaries — separating data access, business logic and presentation where they have blurred — so it becomes possible to change one part without breaking three others. Where migration is the goal, that same boundary work defines the seams along which the system can be moved to Python piece by piece, each component replaced behind a stable interface while the rest keeps running.
Performance
For the text-heavy, batch-oriented work Perl was built for, its performance is rarely the problem — mature Perl scripts chew through logs and data files perfectly well. The performance issues we actually find in legacy systems are structural: scripts that reprocess everything when they could process incrementally, database queries built in loops, unbounded memory growth on large inputs, and startup overhead in web code that was never designed for the request volumes it now serves.
We fix these by measuring first — profiling with the tooling Perl provides rather than guessing — and then addressing the genuine bottleneck. That might mean batching database work through DBI, streaming large files instead of slurping them into memory, or moving a heavy CGI script to a persistent model. We are also honest when performance limits are a reason to migrate: if a system has outgrown what its Perl design can reasonably deliver, we will say so rather than tuning it forever.
Security
Security is often the most pressing reason to bring senior attention to old Perl. Code written in an earlier era frequently predates today’s expectations: SQL built by string concatenation rather than placeholders, user input passed unchecked to shell commands, CGI scripts with no input validation, and taint mode switched off. Add dependencies from a CPAN version that has not been touched in a decade, and the attack surface can be considerable — and invisible until someone looks.
We treat securing a legacy Perl system as a first-class piece of work: auditing for injection and command-execution risks, moving database access to parameterised queries through DBI, validating and sanitising input, enabling taint checking where it belongs, and patching or replacing vulnerable modules. Because much of this code sits behind a login or inside a pipeline, these risks are easy to ignore — right up until they are exploited. We would rather find them first.
Scalability
Scaling a legacy Perl system is usually less about raw throughput and more about operational resilience: can it recover from failure, can it be run by more than one person, can it be changed safely as demands grow. Old Perl often scales badly not because the language cannot cope but because the code has no tests, no clear structure and no documentation, so every change is a gamble and nobody wants to touch it. That fragility is the real ceiling.
We raise that ceiling by making the system safe to operate and evolve — tests around critical behaviour, clear boundaries, proper logging and error handling — so it can absorb growth without a rewrite. Where genuine scale is required beyond what the existing design supports, we are candid that the pragmatic answer is often to migrate the load-bearing parts to Python or split them into services, rather than pushing an ageing Perl monolith past what it was ever built to do.
Perl integrations & ecosystem
The technologies we most often pair with it — each links to how we work with it.
How we work
We start by understanding what you actually have and what it does in production — reading the code, mapping dependencies, and capturing the behaviour the business relies on, especially the parts no living person can fully explain. Only then do we recommend a direction: maintain and harden, migrate incrementally, or, occasionally, leave it well alone. We put that recommendation to you honestly, including the option that earns us the least work, because our job is to reduce your risk rather than maximise ours.
When we do change Perl, we change it safely — tests around real behaviour first, small verifiable steps second, and no clever rewrites of code that already works. When we migrate, we do it in slices, running old and new side by side and checking outputs match before anything is switched over. The senior engineer who assesses your system is the one who works on it; we operate what we build, so we favour the durable, boring path over the impressive-looking gamble every time.
The service behind it
Delivered throughCustom Software DevelopmentWhat we build with Perl
The disciplines this technology most often shows up in — from a first build to taking over and stabilising an existing one.
How we deliver
- 01
Discover
We map the system, the constraints and the business it serves — including the parts nobody documented.
Architecture brief
- 02
Architect
Decisions get made, written down and defended before a line of production code exists.
Decision records
- 03
Build
Short cycles against working software. You see progress in the product, not in a status deck.
Shipping increments
- 04
Operate
Monitoring, incident response and iteration. The system is alive, so the engagement is too.
Runbooks & SLOs
Industries we use Perl in
Domain knowledge changes what gets built. A few of the sectors we know before the first meeting.
Also in Languages
Why teams choose us for Perl
We are honest about maintain versus migrate
We have no incentive to sell you a rewrite you do not need or to keep you on Perl indefinitely. We tell you plainly whether to maintain, migrate, or leave it alone — even when the honest answer means less work for us.
Senior engineers who read old code
Understanding a fragile, undocumented twenty-year-old codebase is exactly the kind of work that punishes inexperience. The people on your system are senior and have done this before — there are no juniors learning legacy archaeology at your expense.
We operate what we build
We run the systems we take on, so we optimise for the reality of keeping legacy code alive safely, not for a tidy demo. That means tests, documentation and small, reversible changes over impressive rewrites.
Pragmatic about migration risk
When migration is right, we do it incrementally and verifiably rather than betting the business on a big-bang cutover. Preserving behaviour is the priority; cleverness comes a distant second.
Typical timeline
- 01
Assessment and mapping
One to three weeks reading the code, mapping dependencies and data flow, and establishing what the system genuinely does in production before recommending a direction.
- 02
Stabilise and secure
Putting tests around critical behaviour, patching vulnerable dependencies, closing security gaps, and making the system safe to change — value delivered before any larger decision.
- 03
Maintain or migrate
Either ongoing maintenance and incremental improvement, or a staged migration to Python delivered slice by slice with behaviour verified against the original at each step.
- 04
Handover and documentation
Turning tribal knowledge into documentation and tests so your team can own the system, whether it stays in Perl or has moved on.
How pricing works
- A fixed-price assessment of an existing Perl system — mapping what it does, its risks, its dependencies, and an honest maintain-versus-migrate recommendation — as a low-commitment first step.
- Ongoing senior maintenance and support for a legacy Perl system, priced monthly, where you want continuity and someone who reliably understands the code.
- Fixed-scope migration engagements — moving a defined part of a Perl system to Python — quoted once the assessment has established the real scope and risk.
Hire Perl engineers
Need Perl capacity on your own team? We embed named senior engineers into your existing team — reporting to your leads, working in your rituals — so you add capacity without a hiring cycle.
Hire Perl engineersCommon questions
Should we start a new project in Perl?
Almost certainly not. For new, greenfield work in 2026 there is very little reason to choose Perl over Python, which gives you a comparable scripting model with far better readability, a much larger and younger hiring pool, and a healthier ecosystem. We work with Perl chiefly to maintain and migrate existing systems; if you are starting something new, we will steer you toward a modern language.
Our Perl system works fine — why touch it?
If it genuinely works and you fully understand it, sometimes the right answer is to leave it alone, and we will say so. But “works fine” often hides real risk: no tests, unpatched dependencies, security gaps, and only one person — perhaps none — who understands it. Making a working system safe to operate and change is usually worth doing before it fails at an inconvenient moment.
Should we migrate our Perl to Python?
Frequently yes, but not always, and rarely all at once. Migration makes sense when hiring is a struggle, the code is hard to maintain, or the system needs to grow beyond what its Perl design supports. When it is right, we do it incrementally — moving one component at a time and verifying the new behaviour matches the old — so the business is never exposed to a single risky cutover.
Can you maintain Perl we no longer understand?
Yes — this is much of what we do. We reverse-engineer what an unowned system actually does, capture that knowledge in tests and documentation, patch its dependencies, and remove the single-point-of-failure risk of code only one departed person understood. Whether it then stays in Perl or is migrated is a separate, informed decision you can make afterwards.
Is Perl a security risk?
The language itself is not, but old Perl code often is. We regularly find SQL built by string concatenation, unchecked input passed to shell commands, disabled taint checking, and decade-old CPAN modules with known vulnerabilities. Auditing and closing these gaps — parameterised queries, input validation, patched dependencies — is one of the most valuable things we do on a legacy Perl system, precisely because the risks stay invisible until they are exploited.
Building on Perl?
A technical conversation with the engineers who would do the work. If we are not the right fit, we will say so on the call.