How to Handle Migration Resistant Applications (part 2) Technical Debt & Complexity

In part 1 I introduced the idea of Migration Resistant applications:


Migration Resistant applications are legacy applications currently hosted on dedicated in-house or private data center servers that have one or more attributes that make them difficult to migrate to the cloud. These are the applications that are always dropping to the bottom of the list when prioritizing applications to be moved to the cloud.


As I suggested in the first post some moves are so complex that they require expert assistance like a specialized piano mover to safely transport a grand piano. While applications with the following characteristics will benefit from expert assistance in migrating to the cloud, there are preparatory steps that should be started in-house and/or explicitly budgeted for when engaging an outside expert.


In this post I examine more deeply five attributes of Migration Resistant applications that are focused on technical complexity and various forms of “technical debt”


Technical debt (also known as design debt or code debt) is a concept in software development that reflects the implied cost of additional rework caused by choosing an easy solution now instead of using a better approach that would take longer. More at Wikipedia.


Preparing to Move your Migration Resistant Application

#1 Customizations to a Third-Party Application - Your third-party application (ERP, CRM, Financial) has so many customizations that it is barely recognizable as the original licensed application.


Businesses often purchase standard third-party applications with good intentions to stick close to the industry standard processes it supports. Over the years complex realities of business evolve leading many organizations to write custom extensions and bolt-ons. Each custom module, feature, data structure and extension creates an additional failure point in migration to the cloud.


Heavily customized third-party applications are almost always frozen at an earlier version of the core application in order to avoid refactoring the customizations with each major upgrade. Migration to the cloud brings to the forefront the issue of porting old versions versus upgrading.


If your application is heavily laden with custom modifications, consider these steps to help prepare your organization to migrate this kind of application:


  • Determine if it’s more cost effective to port older versions or to upgrade the core and refactor all the extensions. Make this decision early as it drives many other decisions.
  • Reach out to peers in other organizations who have recently gone through migrating the same third-party application to the cloud. Although your customizations are different, their experiences can help you avoid costly missteps.
  • Update documentation on custom extensions and make sure unit tests are in place.
  • Work with the third-party vendor to get the latest guides and tutorials for managing a migration for all the standard parts of the application.


#2 Minimally-Documented Custom Application - Your custom application is uniquely suited to your organizational needs but it has been built up in layers over many years and documentation hasn’t kept up. Hidden/undocumented features, integrations, data flows, reports and dependencies make you reluctant to migrate.


Minimally-documented incremental development leaves current developers afraid to modify functions and variables because an undocumented portion of the code might depend on that function.


Here are three actions you can take to mitigate the risk of moving a minimally-documented custom application:


  • Make the investment to document at least the core mission critical components and integrations. Use legacy code analysis tools to help you identify all functions and trace out dependencies.
  • Rationalize the application. If components and modules are no longer used, eliminate them. Refactor key modules to reduce technical debt before migrating the whole application.
  • Improve your test coverage. Update or create tests for all significant features, dataflows, business logic and functions in the custom application so that you can validate the application after completing the move.


#3 Data Structure Complexity - Your databases contain hundreds, even thousands of tables and include many constraints, operational triggers, stored procedures and ETL processes embedded in the database layer.


Applications that rely on complex data models with hundreds or even thousands of tables are daunting to consider migrating. Migrating to the cloud also offers a prime opportunity to evaluate your organization’s historical choice of database vendor. Some organizations are switching to open source database engines when they move to the cloud rather than continue with a proprietary database engine.


The task of migrating an application with complex data models isn’t driven just by the number of tables. The migration takes on additional complexity when your enterprise application has embedded many business rules and logic into the database layer in the form of constraints, triggers, stored procedures and ETL processes.


Three actions to consider when preparing to migrate an application high in data structure complexity:


  • Make the database platform decision first. That may also determine which cloud provider(s) you can actually consider for hosting.
  • Document and evaluate all the embedded business logic. Do you still believe that embedding that particular function or trigger in the database layer is the best choice? If not, this move will represent the best opportunity for re-architecting and refactoring that portion of the application.
  • Evaluate your data archiving requirements at the same time and make sure your cloud solution is able to meet your requirements for disaster recovery and regulatory compliance.


#4 Dependency Rot - Your application is dependent on old versions of languages, libraries and frameworks, some of which are no longer supported by a vendor.


Applications are built using programming languages, code libraries and frameworks. Those software components each have a life-cycle of their own. They evolve, introducing new functions and features, going through multiple releases sometimes stretching over a couple of decades. And, sometimes they fade from popularity so deeply that vendor support disappears.


Each time a component on which your application is built goes through a version release, upgrade or even just a patch, your organization is faced with a choice. Oftentimes the value of a new version is outweighed by the disruption and risk and so organizations stay with an older version of a software language or framework.


Repeated decisions to not upgrade leads to “dependency rot.” Many or even most of the components that your application depends on are now unsupported.


Migrating an application with many unsupported components from a stable dedicated server under your complete control to a cloud provider where hardware, BIOS, drivers and other low-level system settings may not be under your control creates multiple new points of failure.


Three actions to address dependency rot and get ready to migrate to the cloud:


  • Document the dependencies and document every language, library, component or framework in use.
  • Assess security vulnerabilities in each library and prioritize critical updates that must be addressed.
  • Create a version update plan before doing the cloud migration plan.
  • Execute the upgrades one or two at a time so that you can isolate code that needs to be refactored because of a change in an underlying component.


#5 Tightly Coupled Integrations - Your application has multiple tightly coupled integrations with other applications.


To the degree that your enterprise application is tightly coupled with other custom or third-party applications that also run on your own dedicated servers, you understand that migrating that application to the cloud will carry an additional level of complexity in network, security and access control.


Four actions you need to make in preparation for migration:


  • Review and update documentation for each current state integration point.
  • Develop a migration sub-plan specific to the integration points including requirements from owners of both systems. This plan should accommodate transition integrations during the migration process as well as final system state.
  • Create integration specific tests to assure both the development team and the broader organization that integrations remain valid post- migration.
  • Decide whether tight integration is still the right strategy for the final state or whether this migration represents an opportunity to move to a more service oriented style of integration (i.e. containers, microservices and APIs).


Budget to Pay Off Technical Debt

These five attributes of Migration Resistant application each contribute uniquely to technical debt.


Paying down or paying off technical debt is an important part of of getting an application ready for migration to the cloud. Make sure your budget includes room for these preparatory actions, not just the move itself.


In my next post I will examine three attributes of corporate and regulatory complexity which also create resistance to migrating your enterprise applications to the cloud.

Tim Michalski

Written by Tim Michalski

Tim Michalski is the founder & CEO of Lighthouse Software, a legacy software support and modernization firm that specializes in the delicate transition from older, reliable software systems to newer, modern technologies.

For nearly 30 years since that day, Tim has passionately devoted most of his conscious hours towards becoming an expert software engineer and experienced entrepreneur. In that time, Tim built Lighthouse Software from the ground-up and championed the cause of restoring existing technology investments with iterative modernization over time to lower risks and gain a competitive advantage for his clients. Clients include numerous Fortune 500 companies to small technology firms in banking, healthcare, and government.