Migrating Off a Legacy System With No Original Developers and No Downtime Allowance
A forensic method for replacing an end-of-life contract, billing or field service system that nobody left can explain, without a day where invoicing stops.
When a contract and invoicing system is being end-of-lifed, its original developers are gone and billing cannot stop for a day, treat the migration as forensics rather than a data load. First preserve the legacy system and prove you can restore it somewhere safe. Reverse-engineer the data model from the database itself, not the documentation. Rebuild the business rules from historical outputs, such as past invoices against their inputs, and turn each into a test case. Name the few processes that must never break. Run the new system in parallel with daily reconciliation, then cut over one process at a time with a rehearsed rollback. Scope it with a paid discovery whose written outputs make a fixed price credible.
What makes a migration with no original developers different from an ordinary one?
In an ordinary migration the hard part is the data. In this one the hard part is that nobody can tell you what the system does. The people who wrote the contract logic have left, the documentation describes a version from years ago, and the behaviour that matters most to the business, such as how an invoice is calculated, lives in stored procedures, scheduled jobs and code that nobody alive has read end to end. The system is a black box that still produces correct money every month, and the only reliable evidence of its behaviour is what it has already produced.
That changes the method. You cannot write requirements by interviewing the authors, so you derive them from the database and from historical outputs, and you prove the new system against those outputs before it is trusted with a single live invoice. If your problem is a smaller, simpler tool such as an Access database or a set of spreadsheets, replacing a legacy Access database or in-house CRM is the better starting point.
| Question | Ordinary migration | Black-box legacy migration |
|---|---|---|
| Where requirements come from | Workshops with the people who run and built the system. | The database, the code that survives and years of historical outputs. |
| What the documentation is worth | A reasonable starting point. | A hypothesis to test, never a specification. |
| How correctness is proven | Record counts and user acceptance. | Reproducing past outputs from past inputs, line by line, plus daily reconciliation in a parallel run. |
| The biggest risk | Dirty or duplicated data. | A rule nobody knew existed stops firing, and the first sign is a customer disputing an invoice. |
| What happens to the old system | Switched off after cutover. | Kept restorable and read only as the audit source for as long as obligations require. |
Why must you prove you can restore the legacy system before touching anything?
Because the migration itself is the riskiest thing that will ever happen to that system, and if anything goes wrong during extraction, analysis or a failed cutover, the only fallback is the legacy system working exactly as it did. On an end-of-life platform, with no one who has ever rebuilt it, "we have backups" is an assumption until someone has restored one. Proving restore comes first, before any analysis query runs against production.
- Capture everything the system needs to run, not just the database: the application binaries or installers, server and operating system configuration, runtime and database engine versions, licence keys, service accounts, scheduled tasks, file shares, report templates and any certificates it depends on.
- Restore the full system into an isolated environment that cannot send invoices, emails or files to real customers or connected systems.
- Prove the restore is real by reproducing a known historical output there, for example regenerating last month's invoice run and comparing it with what was actually issued.
- Write the restore procedure down as a runbook and have someone other than its author follow it. That restored copy becomes the forensic workbench, so analysis and experiments never touch production.
- Record the date the platform, hosting or vendor support actually ends, and what can be done to extend it safely if the migration needs more time. A deadline you have measured is easier to plan against than one that has been rumoured.
How do you reverse-engineer the data model when the documentation cannot be trusted?
From the database itself, on the restored copy. Documentation tells you what someone intended; the schema, the constraints and the data tell you what actually happens. The goal is a data model you can defend line by line, with every table marked as live, historical or dead. Mapping that model into the target, the load tools and validation are mechanics already covered in the data migration guide, so this stage concentrates on understanding the source.
- Read the catalogue: tables, columns, data types, primary and foreign keys, indexes, views, triggers, stored procedures, functions and scheduled jobs. Old systems frequently enforce relationships in code rather than with foreign keys, so infer the missing ones from naming and by testing which joins actually hold.
- Profile the data: row counts, date ranges of real activity, null rates, distinct values in status and type columns, and columns that were repurposed years ago to hold something different from their name.
- Trace behaviour: on the restored copy, have a user walk through each real process, such as creating a contract, logging a visit and running billing, while a database trace records which tables, procedures and jobs are touched. This finds the logic that runs behind the screens.
- Map the outputs back to the tables: for each invoice, report, export or file the system produces, find the query or procedure that builds it. Those are the places the business rules live.
- Inventory every interface: what reads from or writes to the database, on what schedule, as which account, and who depends on it.
How do you recover business rules that nobody ever wrote down?
By treating historical outputs as the specification. The system has been issuing invoices, renewals and work orders for years, and each of those is a worked example of the rules: a known set of inputs and the output the business accepted. Reverse-engineer each rule from those examples, write it down in plain language, and capture the examples as test cases the new system must pass. Where code survives, read it to confirm the rule, but when the code and the outputs disagree, the outputs are what customers were billed.
- Sample deliberately, not randomly. Pick outputs that exercise the edge cases: contracts starting or ending mid-period, price changes, cancellations, credit notes, multi-site customers, visits over allowance, and anything finance remembers having to query.
- For each sample, gather every input the system had at the time and the output it produced, then work out the calculation until you can reproduce the output exactly from the inputs.
- Write each rule as a numbered entry in a rule catalogue: the rule in plain language, where it lives in the legacy system, the example outputs it was derived from, and the business owner who confirms it.
- Turn each example into a test case with given inputs and an expected output to the penny. Together they form the regression suite the new system has to pass before parallel running begins, and they stay useful for every later change.
- When you find the legacy system doing something wrong, do not silently copy it or silently fix it. Record it, and have the business owner decide in writing whether the new system replicates the behaviour or corrects it from a named date.
What does this look like for Field Service contract logic?
The example below is hypothetical and illustrative, not a client project. Imagine a maintenance company whose in-house field service system holds service contracts, schedules planned visits and bills monthly. The contract logic was written by developers who left years ago. Comparing sample invoices with the contracts and visit records behind them surfaces rules like these, each of which becomes a test case.
In a Dynamics 365 Field Service target, the recurring parts map to agreements, with agreement booking setups generating planned work orders and agreement invoice setups generating recurring invoice records, while the exceptions usually need custom logic. In a custom build they become explicit, tested functions. Either way, the rule catalogue is what makes the mapping checkable. Our Field Service implementation partner guide covers the platform side.
| What the sample invoices show | Inferred rule | Test case to write |
|---|---|---|
| A contract starting on the 18th was billed for part of its first month. | The first period is pro-rated, and the pro-rating basis (calendar days, or a fixed month length) has to be confirmed from several examples. | Given a contract starting mid-month at a known monthly fee, the first invoice equals the amount the legacy system produced for the same dates. |
| A visit booked soon after an earlier visit to the same asset was not charged. | Repeat visits within a set window of a previous visit are treated as a callback and not billed. | Given two visits to one asset inside and just outside the window, only the second is billed. |
| Invoices after a contract anniversary show a higher unit price. | An uplift applies on the anniversary date, not on 1 January, and is rounded in a specific way. | Given a contract crossing its anniversary mid-period, the uplift, the split and the rounding match the historical invoice. |
| Visits beyond the included number appear as a separate line. | Visits over the contract allowance are billed at a contract-specific rate, falling back to a standard rate when none is set. | Given a contract with and without its own rate, the over-allowance line uses the correct rate. |
| A cancelled contract produced a credit note rather than a reduced invoice. | Cancellation mid-period credits the unused portion on a separate document. | Given a cancellation date, a credit note is produced for the expected amount and the original invoice is untouched. |
Which processes must never break, and how do you find them?
Not every process deserves the same protection, and trying to protect everything equally is how migrations stall. Identify the handful where a single day of failure costs money, breaches a contract or reaches a customer, and design the whole programme around keeping those running. Everything else can tolerate a short manual workaround during cutover.
- Follow the money first: invoice generation, credit notes, renewals and price changes, and the export or interface that sends billing to the finance system.
- Then the contractual obligations: planned maintenance visits that must be scheduled on time, response commitments and anything a regulator or customer audits.
- Then the outputs other systems or customers consume automatically: files, feeds and reports whose absence would not be noticed until something downstream fails.
- For each, write a one-line register entry: the process, what "broken" looks like, how quickly it would be noticed, who owns it, and which reconciliation check will prove it is working in the new system.
- If the legacy system also keeps the general ledger, that part belongs in your finance system. Solzet does not implement Dynamics 365 Finance, Business Central, NAV, Finance and Operations or other ERP systems; we integrate the new contract and billing system with the finance system you already run.
How do you run the old and new systems in parallel with daily reconciliation?
Parallel running means both systems receive the same real inputs and produce their outputs independently, while only the legacy system is allowed to send anything to customers. Every day, an automated comparison checks the outputs and every difference is explained before the next day. It costs effort, because inputs have to reach both systems, but for processes that must never break it is the only evidence strong enough to justify cutover.
| Daily check | What is compared | What a difference usually means |
|---|---|---|
| Invoice totals | Invoice count and total value per customer and per contract for the day or billing run. | A rule missing from the catalogue, or an input that reached one system but not the other. |
| Invoice lines | Line by line amounts, quantities, rates and tax for a sample and for every flagged difference. | Rounding, pro-rating or uplift logic implemented slightly differently. |
| Work orders and visits | Planned visits generated per contract and their dates. | Scheduling or recurrence rules that differ at period boundaries. |
| Contract state | Active, suspended, renewed and cancelled contracts, and their current prices. | A status transition or a price change applied on a different date. |
| Outbound interfaces | Records and control totals in each export or feed the finance system and others receive. | Mapping or timing differences in the interface rather than in the rules. |
- Classify every difference as a defect in the new system, a legacy defect the business has decided to correct, or a timing difference, and keep the log. The log is the evidence you take to the cutover decision.
- Agree the exit criteria before parallel running starts, for example a defined number of consecutive billing cycles with every difference explained, so the end is a decision against evidence rather than a feeling.
How do you cut over one process at a time with a rollback you have actually tested?
Move processes individually, in an order that starts with the lowest risk and ends with billing, so each cutover is small enough to reverse. A big-bang cutover of a black-box system bets the business on every unknown being found in advance, which is the one thing you cannot guarantee.
- Give each process a cutover date, an owner, and a rule that from that date new records for the process are created only in the new system.
- Define the rollback trigger in advance: which reconciliation failure, customer impact or missed deadline sends the process back to the legacy system, and who decides.
- Plan the data path back, because records created in the new system during the cutover window must reach the legacy system if you roll back, whether by a reverse sync or a scripted re-key.
- Rehearse the rollback on the restored copy before the real cutover. A rollback that has never been run is a hope, not a plan.
- Keep the reconciliation running after each cutover until the process has been through a full billing cycle in the new system.
- If the programme is already in trouble, with a stalled cutover or a new Dynamics 365 system that is not trusted, that is a rescue rather than a migration, and our Dynamics 365 project rescue and takeover service sets out how that is handled.
Should the target be Dynamics 365, Power Platform or a custom stack?
We recommend the right solution - whether that's Microsoft Dynamics 365, Power Platform, or a custom-built CRM. Some businesses need the Microsoft ecosystem. Others need full control without licensing. We deliver both. The forensic method is the same for all three; what differs is how much of the recovered rule catalogue the platform already covers and who will own the logic afterwards.
| Target | Fits when | What to watch |
|---|---|---|
| Dynamics 365 Field Service or Customer Service | Contracts, planned visits, scheduling, a mobile app for technicians and service levels are the core of the business, and you are comfortable with per-user Microsoft licensing. | Unusual contract and billing rules still need custom logic on top of agreements, and each piece of it must pass the same test cases. |
| Power Platform on Dataverse | You run Microsoft 365, the process is specific but does not need the full Field Service scheduling and mobile capability, and premium licensing is acceptable. | Rule-heavy billing logic belongs in tested server-side code rather than in a web of flows nobody can read in five years, which is how the legacy system got here. |
| Custom-built system | Licensing does not fit, the contract logic is the business differentiator, or you need to host and own the code and data outright. | You are replacing one bespoke system with another, so documentation, automated tests and a maintained team are part of the scope, not extras. |
Which platform should replace the legacy system?
Can afford licensing and want the Microsoft ecosystem
Dynamics 365
Microsoft 365, Teams and Outlook integration, a mature partner ecosystem, Copilot, and apps for sales, service and field operations that are configured rather than built.
Need full control and zero licensing
Custom CRM
A CRM built on React, Node.js, PostgreSQL or .NET that you own outright: your data model, your hosting, no per-user subscription, and features shaped exactly to your process.
Not sure which fits
We help you decide
A short discovery weighs licensing budget, process complexity, integrations and long-term ownership, then recommends one path. We deliver both, so the recommendation has no reason to lean.
How do you scope and price a migration when nobody knows what the system does?
In phases, because a fixed price for the whole migration before anyone understands the system is a guess with a contingency on top. The general case for discovery before a fixed price, and how to compare competing migration quotes, is set out in scoping and pricing a legacy CRM migration. For a black-box system, discovery has to produce forensic outputs as well as the usual data health and mapping work.
| Phase | What it produces | Why it comes before a fixed price |
|---|---|---|
| Preserve | A captured, restored and runbooked copy of the legacy system, and a proven reproduction of a historical output. | Without it there is no safe fallback and no workbench for analysis. |
| Forensic discovery | The reverse-engineered data model, the interface inventory, the rule catalogue with its test cases, the must-never-break register and a platform recommendation. | These are the unknowns that make fixed prices break; once written down, a different partner could price the work from them. |
| Delivery per process | The build, the test suite passing, a parallel run with its reconciliation log and a rehearsed rollback, for one process or group of processes at a time. | Each increment can carry a fixed price tied to the rules and tests discovery found. |
| Retire | The legacy system locked read only, its retention plan agreed and the restore runbook kept current. | The audit source has to be priced and owned, not left to chance. |
What should happen to the legacy system after the last process moves?
Keep it, read only, as the audit source. Customers dispute old invoices, auditors ask how a figure was calculated, and a migrated record occasionally needs checking against what the old system said. None of that requires the legacy system to stay writable, and all of it requires it to stay readable and restorable.
- Remove write access at the database and application level on the date the last process cuts over, and record that date.
- Keep the legacy record identifier on every migrated record, so any record in the new system can be traced back to its source.
- Decide with finance and legal how long the legacy data must remain available, and whether the running system or a restorable archive with a documented way to query it is the right form for that period.
- Migrate only the history the business works with day to day into the new system, and leave the rest in the audit source rather than paying to move and maintain it.
- Keep the restore runbook tested on a schedule, because a read-only archive nobody can open is not an audit source.
What do people ask us?
How do you migrate off a legacy system when the original developers are gone?
Treat it as forensics. Preserve the system and prove you can restore it, reverse-engineer the data model from the database, rebuild the business rules from historical outputs such as past invoices against their inputs, and capture each rule as a test case. Identify the processes that must never break, run the new system in parallel with daily reconciliation, and cut over one process at a time with a rollback you have rehearsed. Keep the legacy system read only as the audit source afterwards.
How can we migrate without a day where billing stops?
By never switching billing off in the old system until the new one has proven itself. Run both in parallel on the same inputs, let only the legacy system send invoices, reconcile the outputs every day and explain every difference. Move billing last, after lower-risk processes have cut over, and only once agreed exit criteria are met, with a tested rollback ready if a reconciliation check fails.
How do you find business rules in a system with no documentation?
From evidence rather than memory. Trace which tables, procedures and jobs each process touches on a restored copy, then take a deliberate sample of historical outputs that cover the edge cases and work out the calculation until each output can be reproduced exactly from its inputs. Each rule goes into a catalogue with its source and a business owner, and each example becomes a test case the new system must pass.
Can our custom field service contract logic be moved to Dynamics 365 Field Service?
Usually the recurring parts map well to Field Service agreements, which generate planned work orders and recurring invoice records, and the unusual rules such as bespoke pro-rating, callback windows or anniversary uplifts need custom logic on top. The rule catalogue and its test cases show exactly how much custom logic is needed before you commit. If licensing does not fit, the same rules can be built into a custom system instead.
Can you give us a fixed price before anyone understands the system?
Not a credible one. A fixed price before discovery either hides a large contingency or pushes the risk back to you as change requests. The honest route is a preservation step and a separately scoped forensic discovery that produces the data model, the rule catalogue with test cases, the must-never-break register and the interface inventory, after which each delivery increment can carry a fixed price tied to what was found.
What if the legacy system does something wrong?
Record it and make it a business decision, never a silent choice by the developer. The business owner decides in writing whether the new system replicates the behaviour, for example to keep existing contracts consistent, or corrects it from a named date. The decision is captured in the rule catalogue and the test case, so the parallel run treats the difference as expected rather than as a defect.
How long should we keep the old system after migration?
As long as your finance, legal and contractual obligations require access to the records it holds. Lock it read only at the final cutover, keep the legacy identifier on every migrated record, and keep the restore procedure tested. Whether it stays running or becomes a restorable archive with a documented way to query it is a decision to make with finance and legal during discovery.
Does Solzet migrate ERP or finance systems as well?
No. Solzet migrates contract, service, field service and CRM processes onto Dynamics 365 Customer Engagement, Power Platform or a custom system built on React, Node.js, PostgreSQL or .NET. We do not implement Dynamics 365 Finance, Business Central, NAV, Finance and Operations or other ERP systems. Where the legacy system feeds a general ledger, we integrate the new system with the finance system you already run.
Where should you go next?
Data migration guide
The mechanics of the load: mapping, tools, validation and the zero budget path from Excel, Access or legacy systems.
Scoping and pricing a legacy CRM migration
Why a fixed price needs discovery first, what discovery must produce and how to compare migration quotes.
Replacing a legacy Access database
Choosing between stabilising, Power Apps and a custom application when one ageing tool is failing.
Dynamics 365 project rescue and takeover
When a migration or implementation has already stalled or failed and someone needs to take control.
Custom CRM Development
A system you own on React, Node.js, PostgreSQL and .NET, for organizations Microsoft licensing does not fit.
Field Service implementation partner
What to expect from a Dynamics 365 Field Service implementation and how to choose a partner.
Which solution is right for your business?
Tell us what you need. A senior consultant replies within one business day with a recommendation - Dynamics 365, Power Platform, or a custom-built CRM - not a sales script.