Legacy Application Modernization Services for the System Nobody Wants to Touch
A support date passed. An auditor flagged the platform. The one engineer who understood the code has left. Whatever brought you here, the system still runs the business and still has to be moved. Pillai Infotech assesses it, prices it honestly, and migrates it in pieces that can be rolled back — from India, in your working hours.
Every engagement starts with a 14-day risk-free trial — you pay only if you are satisfied.
Nobody Searches for This Casually.
Something Happened This Month.
Legacy systems are tolerated for years and then become urgent in a week. The trigger is almost always external, dated, and attached to somebody else's calendar. Being clear about which one applies to you changes the shape of the whole programme, because a compliance deadline and a resignation letter call for very different sequencing.
A vendor support date has passed
The platform is out of support, security patches have stopped, and the risk is now carried by you rather than the vendor. The date is public, so your auditor already knows it.
Cyber insurance or audit flagged it
An unsupported runtime has been named in a renewal questionnaire or an audit finding. A remediation plan with dates is now required, and hoping the question goes away is no longer available.
The person who understood it has gone
Retirement or resignation has removed the only working documentation the system had. Knowledge that lived in one head is now recovered from code and data, which costs more but is still recoverable.
A cloud programme has stalled on it
Everything else moved. This one application cannot be lifted because it depends on a local file share, a scheduled task on a named server, or a licence bound to hardware. The programme is now blocked by a single system.
A compliance requirement cannot be met
Accessibility conformance, data residency, audit logging or consent handling has been mandated, and the current interface simply cannot express it without being rebuilt.
A one-day change now takes six weeks
Every change breaks two other things, so changes are batched, then feared, then avoided. Delivery has quietly stopped, and the business has started building spreadsheets around the system instead of through it.
What Actually Makes a System Legacy?
Age is the wrong test, and it is the one most commonly used. A system is legacy when it can no longer be changed safely. Everything else is a symptom of that.
A fifteen-year-old application with a working build, a test suite, three people who understand it and a supported runtime is not legacy. It is simply mature, and money spent replacing it is money burned. A four-year-old application with no tests, one author who has left, a dependency that was abandoned upstream and a deployment process that only runs from one laptop is very much legacy, whatever the commit dates say.
Five properties are checked when a system is classified. Can the source be built today, from scratch, on a machine nobody has ever touched? Is there enough automated testing that a change can be proven not to have broken something else? Is the runtime still receiving security fixes from whoever publishes it? Can people be hired or trained to work on it at a sane cost? And are the business rules written down anywhere other than in the code and in somebody's memory?
Systems that fail one of those tests are usually repairable in place. Systems that fail three or more are the ones where the cost of every future change compounds, and where doing nothing has a price even though no invoice arrives for it. That distinction is what the assessment is designed to establish before anybody argues about target technology.
Triage the Portfolio Before Picking a System
Most modernization budgets are spent on whichever application complained loudest. A portfolio is scored on two independent axes first, and the sequence falls out of the scoring.
Axis one: business value
Revenue touched, headcount dependent on it, regulatory obligations it satisfies, and what happens on the day it is unavailable. Value is scored from evidence rather than opinion, because every department believes its own system is critical. Transaction volumes, support tickets and downtime history settle the argument quickly.
Axis two: technical health
Supportability of the runtime, buildability of the source, test coverage, dependency risk, defect rate, change lead time, and the size of the pool of people who can work on it. Each is measurable, and measuring them is far cheaper than debating them.
High value, poor health
Modernize first. This quadrant is where the risk lives and where the money should go. It is also, reliably, where the least documentation exists.
High value, good health
Leave it alone and invest in it. Keeping it healthy is cheaper than any migration, and it is often the reference for how the modernized systems should look.
Low value, poor health
Retire it, or replace it with a product. Migrating a system that thirty people use once a month is the most common way modernization budgets are wasted.
Low value, good health
Ignore it. It costs little and breaks rarely. Attention spent here is attention taken from the first quadrant.
Interfaces between systems are scored too. An application in the retire quadrant that eleven other systems read from is not really a retirement candidate until those readers have somewhere else to go, and that dependency is easy to miss when applications are assessed one at a time.
Pick a Disposition: The Industry R Options
The set of choices below is the industry-standard disposition framework used across the cloud and modernization field, not something invented here. What matters is applying it per module rather than per system, because one application usually deserves three different answers.
Retain
Nothing is done, deliberately, and the decision is recorded with a review date. Effort is near zero. This is correct when the system is stable, cheap to run, out of regulatory scope, and when the change budget produces more value elsewhere. Retain is a decision. Drift is not.
Retire
The system is switched off and its data is archived in a readable, queryable form. Effort is low to moderate, and it is nearly always underestimated because of retention obligations. Correct when usage has collapsed or when another system already does the same job. Every portfolio review finds at least one.
Rehost
The application is moved as-is onto new infrastructure, commonly a virtual machine in a cloud account. Effort is low and the code is untouched. Correct when a datacentre exit has a date on it and the application itself is not the problem. It buys time and changes nothing about maintainability.
Replatform
The application is moved and a small number of components are swapped underneath it: a managed database instead of a self-run one, object storage instead of a file share, a container instead of a named server. Effort is moderate. Correct when running costs and operational toil are the pain, not the code.
Refactor
The code is restructured while its behaviour is held constant: dead code removed, layers separated, tests introduced, dependencies upgraded. Effort is moderate to high and the visible result is nil, which makes it politically hard to fund. Correct when the language and platform are still supportable and only the internals have rotted.
Rearchitect
The structure is changed materially: a monolith is decomposed, batch processing becomes event-driven, a shared database is split behind service boundaries. Effort is high. Correct when scaling, deployment independence or team autonomy is the actual constraint, and only when the existing behaviour is well understood first.
Rebuild or replace
The system is written again from a specification, keeping the data and discarding the code. Effort is the highest of any option and the risk profile is different rather than simply larger. Correct when the domain has moved so far that porting the old logic would carry forward decisions nobody would make again.
Repurchase
A commercial or SaaS product takes over the job and the custom system is retired into it. Effort sits in data migration, configuration and process change rather than in code. Correct when the system does something the whole market does, and painful when it encodes a genuine competitive difference.
In practice a single application is split: the reporting module is retired, the customer-facing screens are rebuilt, the pricing engine is refactored and kept, and the batch jobs are replatformed. Choosing one disposition for an entire system is how programmes end up rewriting code that was working perfectly well.
Platforms This Practice Covers
Migration work is dominated by a small number of platforms that were dominant fifteen to twenty-five years ago and are now hard to staff. These are the ones that come up.
Two of these have enough depth to deserve their own treatment. If the platform in question is Adobe ColdFusion, the end-of-support timeline and the CFML, Lucee and BoxLang target options are covered on the ColdFusion migration service page. If it is a Visual Basic 6 desktop application breaking on current Windows builds, with COM and ActiveX dependencies to unpick, the detail sits on the VB6 to .NET migration service page. Where a module turns out to need a genuine rebuild rather than a port, it is delivered through the same team as our custom software development practice, so the specification and the people do not change hands halfway through.
How a Migration Is Actually Run
Eight stages, in order. Nothing is skipped because a deadline is tight; the sequence is what makes the deadline survivable.
Assessment
The source is taken and built from scratch on a clean machine, which is the first honest test of what actually exists. Screens, reports, batch jobs, scheduled tasks and integration endpoints are counted. The database is profiled. Usage is pulled from logs so that dead features are identified before anybody pays to port them. The output is an inventory, a risk register and a per-module disposition recommendation.
Dependency and risk mapping
Every inbound and outbound connection is traced: third-party controls, COM components, licensed libraries, file drops, printers, scheduled scripts on forgotten servers, and the reporting tools quietly reading production tables. Dependencies with no modern equivalent are flagged early, because they set the ceiling on what is possible and they are the single most common source of mid-programme surprise.
Target architecture
The target is chosen against your constraints, not against fashion. Hiring pool, existing platform commitments, hosting model, data residency and the skills of the team who will own it afterwards all weigh more than benchmark charts. A written comparison of the two or three viable targets is produced, with the losing options and the reasons they lost, and you approve it before code is written.
Incremental or big-bang
The cutover strategy is decided explicitly rather than assumed. Incremental migration is the default because it keeps a rollback available at every step; big-bang is chosen only when the conditions genuinely rule out running two systems together. The criteria that decide this are set out in the next section.
Data migration
Schema archaeology, cleansing and reconciliation, run repeatedly rather than once. This is the stage that consumes the most calendar time on almost every programme, and it is treated as a first-class workstream with its own plan rather than as a task at the end of the build.
Parallel run
Both systems are run against the same inputs and their outputs are compared automatically. Differences are triaged into defects in the new system, latent bugs in the old one, and deliberate improvements. The old system remains the source of truth throughout, which is what makes the exercise safe.
Cutover
A dated runbook is written and rehearsed against a production-shaped copy, including the rollback path and the point of no return. Traffic is moved by cohort where the seam allows it. The rollback window is stated in hours, and it is agreed with your team in advance rather than improvised at two in the morning.
Hypercare and handover
Four to eight weeks of elevated support by the engineers who did the work, followed by a documented transfer of ownership. Documentation, tests, runbooks and recorded walkthroughs are delivered to the people who will maintain the system, and the end date is agreed rather than left open.
Strangler-Fig or Big-Bang? Four Questions Decide It
The incremental pattern, usually called strangler-fig, replaces a system function by function while both versions run, until nothing is left of the original. It is the safer default. It is not always available, and pretending otherwise wastes months.
Can both systems run at once?
Licensing, hardware, data residency and integration limits are checked. Some vendor agreements forbid a second concurrent instance. Where the old system cannot legally or physically be duplicated, incremental migration is off the table regardless of preference.
Is there a seam to route through?
A seam is any boundary where traffic can be intercepted and directed: an HTTP layer with a reverse proxy in front, a message queue, a database view, a service facade, even a shared file drop. Without a seam, requests cannot be split between old and new, and one has to be created before migration begins.
How long can two systems be paid for?
Incremental migration means duplicated licences, duplicated hosting and duplicated support for the length of the transition. That overlap is a real budget line. Where it can only be afforded for three months, the increment size is set to fit inside three months rather than pretending the constraint does not exist.
Is there a hard external date?
A lease expiry, a contract end, a regulatory deadline or a datacentre shutdown can force a single move. Where such a date exists and cannot be shifted, the plan is built backwards from it and the residual risk is stated openly rather than being discovered in the final week.
Two answers in favour of incremental are usually enough to justify it. A big-bang cutover is defensible when the system is small, the users are few, the data is simple and the rollback is genuinely a restore from backup within an agreed window. It is indefensible for a four-hundred-form application used by three thousand people, however tight the deadline is.
Data Migration Is the Largest Line Item
Code can be read. Data has to be excavated. On most programmes the data workstream consumes more calendar time than the application rebuild, and it is the workstream most often estimated as an afterthought.
Schema archaeology comes first. A twenty-year-old database is profiled column by column: which columns are still written to, which are read only by a report nobody runs, which hold three different meanings depending on the value of another column, and which were added for a project that was cancelled in 2011. Column names are unreliable and comments are usually absent, so intent is inferred from the values themselves and confirmed with the people who enter them.
Referential integrity is then tested rather than assumed. Where relationships were enforced only in application code, orphaned rows accumulate silently for years. Child records pointing at parents that were deleted, duplicate keys distinguished only by trailing whitespace, and status codes that exist in the data but not in any lookup table are all normal findings. Each has to be resolved by a rule your team agrees to, because the new schema will refuse to accept them.
Encoding is its own category of pain. Text stored in one code page, read through another, and re-saved has produced two decades of corrupted characters in names and addresses. Dates held as strings in three different formats, numbers stored as text with currency symbols embedded, and historical records written by a version of the software that no longer exists all need parsing rules of their own. Data that predates a schema change often will not parse at all under current assumptions.
Cleansing is where the cost concentrates, and it is usually the single largest item in the migration budget. The decisions are business decisions rather than technical ones: whether a duplicate customer record is merged or kept, whether a transaction with an impossible date is corrected or quarantined, whether twelve years of history is migrated in full or archived separately with a read-only view. Engineers can present the options and the counts. Only your organisation can choose.
Not every legacy estate is a database. One recruitment agency was run entirely on spreadsheets and shared folders, with years of candidate records, job history and file references sitting outside any system of record and more than a terabyte of documents that were not permitted to leave the premises. The manual process was documented before anything was automated, the historic data was migrated so that day one on the new system continued rather than restarted, and the whole programme ran from first conversation to installed system with user acceptance testing completed in two months. That build is written up in our AI recruitment automation case study.
Reconciliation makes the whole thing provable. Row counts, control totals, checksums on financial columns and record-level comparison on sampled sets are run after every trial migration, and the migration is rehearsed repeatedly rather than executed once. A reconciliation report that your finance or compliance team can read and sign is part of the delivery, because the day after cutover somebody will ask whether the numbers still tie out, and the answer has to be evidence rather than reassurance.
Prove It Before You Switch It
A parallel run is the difference between believing the new system works and knowing it does. Production traffic is shadowed into the new system without its results being used, and the two sets of outputs are compared automatically. For a calculation engine that means comparing every computed figure. For a batch process it means comparing generated files byte by byte after known-variable fields are normalised. For a user interface it means scripted journeys run against both.
Differences are triaged into three buckets, and the third one causes the arguments. Some differences are defects in the new system and are simply fixed. Some are latent bugs in the old system that nobody had noticed, at which point a decision is needed about whether the bug is reproduced deliberately because downstream processes depend on it. Some are intended improvements, which must be recorded as such so they are not later reported as regressions.
Cutover itself is a rehearsed procedure rather than an event. The runbook is written with named owners, timings and explicit go and no-go checks, then executed end to end against a production-shaped environment at least twice. The rollback path is rehearsed with the same seriousness as the forward path, because a rollback that has never been tested is a hope rather than a plan. The point of no return is identified and stated: usually the moment the new system begins accepting writes that the old one cannot receive.
Freeze periods are agreed in advance. Changes to the old system are stopped for a defined window before cutover so the data being migrated stops moving, and business events that would collide with the window, such as month-end, payroll or a peak trading day, are mapped before the date is chosen. Cutovers scheduled without reference to the business calendar tend to land on the worst possible weekend.
Done is defined before the work begins, in terms that can be checked. All identified functions available in the new system, reconciliation reports signed, the old system placed into read-only mode with an agreed decommission date, documentation delivered, and the support rota transferred. Without that definition a migration acquires a long tail in which the old system is never quite switched off and both are paid for indefinitely.
When a Migration Is the Wrong Answer
Two honest conversations that most firms selling modernization will not start with you.
When a rebuild beats a migration
Porting old code makes sense when the logic is still correct and only the platform has aged. It stops making sense in three specific situations.
The first is when the domain has changed more than the code. If the way you price, ship, bill or comply has been redesigned twice since the system was written, a faithful port carries forward a model of a business that no longer exists, and the new system is obsolete on the day it launches.
The second is when the business rules are wrong rather than merely old. Where the workarounds have become the process, and where users maintain parallel spreadsheets to correct what the system produces, migrating faithfully migrates the problem.
The third is scale. A system serving thirty people, with a hundred screens accumulated over twenty years of which twelve are used, is often replaced more cheaply by a configured product plus a data migration than by any port. Repurchase is a legitimate answer and it is recommended when it is the right one.
When doing nothing for another year is correct
Deferral is a valid disposition, and it is the right one more often than the modernization market admits. Four conditions have to hold together.
There is no compliance or contractual deadline forcing your hand within the next twelve to eighteen months. The system is stable, with a defect rate and downtime record that support the claim rather than an impression that it feels fine. Extended support can still be bought, or the runtime can be isolated behind network controls that your security team will accept in writing.
And the same budget produces more value somewhere else this year. A migration that delivers no new capability competes directly with work that does, and that comparison should be made explicitly rather than avoided.
Where deferral is chosen, it is chosen with conditions: a review date, a named trigger that reopens the decision, and a small amount of preparatory work such as documenting the build or capturing knowledge from whoever still holds it. That preparation costs little and removes the worst risk, which is the decision being made for you by someone leaving.
What Actually Moves the Price
No rate card is published here, because a rate without a scope tells you nothing. These are the eight variables that determine what a migration costs, and any assessment worth paying for will quantify each of them for your system.
Volume of code, screens and jobs
Lines of code is a crude measure, so screens, reports, batch jobs and stored procedures are counted separately. A form with two fields and a form with eighty are not the same unit of work, and estimates built on file counts alone are the ones that slip.
Third-party and COM dependencies
Every commercial control, ActiveX component, licensed library or abandoned open-source package needs a modern equivalent, a replacement built from scratch, or a compatibility shim. Components whose vendor no longer exists are the most expensive single finding in most assessments.
Database coupling
Business logic living in stored procedures and triggers has to be understood and relocated. Where other systems read and write the same tables directly, the migration expands to include those systems, which is how a single-application project quietly becomes a portfolio programme.
Existing test coverage
Usually zero, and that has a price. Without tests there is no definition of correct behaviour, so a characterisation suite is written against the old system before migration starts. It is real work, it appears on the invoice, and skipping it is how equivalence disputes begin.
Regulatory scope
Systems inside financial, healthcare, aviation or public-sector scope carry validation, documentation and evidence obligations that add materially to effort. The engineering may be identical; the paperwork around it is not, and it has to be budgeted rather than discovered.
Integration surface
Each interface to a bank, a regulator, a partner or an internal system needs its own testing, its own counterpart contact and often its own certification window. Interfaces that depend on a third party responding to email are the ones that set the calendar.
Completeness of the source
Whether the code that is running in production can be built from what is in version control is checked on day one. Missing modules, uncommitted hotfixes applied directly to servers, and binaries with no matching source all add reconstruction work before migration can start.
Data volume and quality
Twenty years of history, several schema generations and inconsistent encoding push the cleansing effort up sharply. Volume alone matters less than variety, because each historical format needs its own parsing and reconciliation rules.
As a rough orientation only: a single-module pilot with a clean source tree and a modest data set typically starts in the low five figures, while a multi-application portfolio programme is funded very differently and is scoped module by module. Anyone quoting a firm number before reading your code is quoting a number they intend to revise.
Timeline Shapes, and What Makes Them Slip
Migration timelines come in a small number of recognisable shapes. Knowing which one you are in matters more than knowing an average, because the shapes have different failure modes.
A single-module pilot runs in weeks. One bounded function is picked, migrated behind a seam, run in parallel and cut over. Its purpose is to calibrate the estimate for everything that follows and to prove the seam works, so it is deliberately chosen to be representative rather than easy.
A single application of moderate size, perhaps forty to eighty screens with a handful of integrations, runs in months, with data work typically taking as long as the application build. A large system with several hundred forms, deep database coupling and regulatory scope runs in quarters, and is delivered as a sequence of independently valuable increments so that value lands before the end.
A portfolio programme covering several applications runs across years and is governed differently. It is funded increment by increment, each with its own business case, so it can be stopped, paused or re-sequenced without stranding half-finished work. Programmes funded as one large commitment are the ones that become impossible to cancel and equally impossible to defend.
Slippage is caused by a short and predictable list. Undocumented business rules surface mid-flight, usually as an exception path that only runs at year end. The one person who understands a subsystem is unavailable, on leave, or has already left. Data quality turns out worse than the survey suggested, which pushes the cleansing effort up after the plan was written. A third-party dependency turns out to have no modern equivalent, forcing a build that was never scoped.
Then there are the two organisational causes. Change freezes for month-end, year-end, peak trading or an unrelated programme remove weeks from the calendar and are almost never in the first plan. And scope creep arrives dressed as sense: since the system is being touched anyway, four new features are added, and the migration stops being a like-for-like exercise that can be verified against the old system. Every one of these is manageable when named early. None of them is manageable when discovered in the final month.
Questions Buyers Ask Before Committing
Six questions that come up on almost every modernization conversation, answered the way they are answered on a call.
How do you assess a system before quoting a price?
A paid discovery is run first, typically over two to four weeks. The source is built from scratch on a clean machine, the dependency graph is extracted, screens and batch jobs are counted, and the database is profiled for coupling and dead structure. Business rules are traced from the code back to the people who still rely on them. What you receive is an inventory, a risk register, a recommended disposition for each module, and a scoped estimate. If the discovery concludes that the migration is not worth doing this year, that is written down too.
Can we keep shipping features while the migration runs?
Usually yes, provided the work is sequenced properly. Feature delivery is protected by migrating module by module behind a routing seam, so the old system keeps serving everything that has not moved yet. Two rules keep this honest: changes made to the old system during the programme are logged and replayed into the new one, and a short freeze is agreed near each cutover. Where a module is being actively rebuilt, new features for that module are queued rather than built twice. A big-bang approach makes this far harder, which is one reason it is rarely recommended.
What happens if the source code is incomplete or will not build?
This is common enough to be treated as a normal starting condition rather than a crisis. Decompilation is used where licensing permits, production binaries are compared against whatever source survives, and missing components are reconstructed from behaviour, logs and database traces. Where a third-party control has been lost entirely, its function is re-specified from the screens and outputs it produced. The build is reconstructed first, because a system that cannot be built cannot be tested, and a migration without a test baseline is guesswork. If reconstruction proves impossible for a module, a rebuild of that module is recommended openly.
Who owns the business rules nobody wrote down?
You do, and recovering them is part of the work. Rules are recovered from three places: the code itself, the data (which shows what actually happened rather than what was intended), and the people who use the system every day. Each recovered rule is written into a specification your team reviews and signs off, because only your organisation can confirm whether a rule is still correct or was a workaround for a problem that disappeared years ago. That specification outlives the migration and becomes the documentation the old system never had.
How can the scope be fixed when the system is undocumented?
It cannot be fixed before discovery, and any firm quoting a fixed price before reading the code is guessing. After discovery the scope is fixed per module rather than across the whole programme. Each module gets a counted inventory of screens, jobs, reports and integrations, and the price is fixed against that count. Anything discovered mid-flight goes through a change register with a stated cost attached, rather than being absorbed quietly and billed later as an overrun. Portfolio programmes are funded module by module so you can stop after any module without stranding the work.
What does handover look like when the migration finishes?
A hypercare period runs first, normally four to eight weeks, during which defects found in production are fixed by the same engineers who did the migration. Alongside it the handover package is assembled: architecture and data-model documentation, the recovered business-rule specification, the test suite written during the migration, runbooks for deployment and rollback, and recorded walkthroughs. Sessions are run with the people who will own the system afterwards, not only with management. Ownership transfers on an agreed date, and continued support beyond that date is optional rather than assumed.
Is anything committed before the assessment has been read?
The assessment is free, and every engagement that follows starts with a 14-day risk-free trial — you pay only if you are satisfied. Those two weeks are spent reading the system rather than pitching a plan for it. If the honest conclusion is that migration should be deferred, or that a packaged product fits better, that is what gets said.
Start with an assessment, not a proposal.
The first conversation is with an engineer who will ask what the system does, what triggered the search, and whether the source still builds. No slide deck, no rate card, and no recommendation to migrate before the code has been read. Where the honest answer is to defer for a year or to buy a product instead, that is what you will be told.
Chat for a quick question. Use the form to send a brief, a spec or your requirements in detail.