Code Sustainment Across Generations

Written by

in

The central problem

Every successful codebase outlives at least three things, and they rarely die at the same time:

  1. The product that originally compiled it (the IDE, the toolchain, the vendor’s commercial interest).
  2. The Platform or environment it targeted (the OS, the runtime, the browser, the hardware).
  3. The people who understood it (the original authors, the cohort who maintained it).

When all three align, sustainment is routine. When they drift apart, the codebase enters a sustainment gap — it still runs, but the means to rebuild, modify, or safely operate it are eroding. The history of our industry is a series of these gaps. The VB6 situation is one instance of a repeating pattern that began with COBOL and will repeat with whatever you migrate to next.


The three failure axes

Code does not die from a single cause. It dies along three independent axes, each on its own clock:

flowchart LR
  A["Loss axis"]
  A --> P["Product<br/>The compiler/IDE/vendor<br/>withdraws support"]
  A --> E["Environment<br/>The target OS/runtime/platform<br/>moves on"]
  A --> D["People<br/>The cohort who understand it<br/>retire or leave"]
  P --> G["Sustainment gap"]
  E --> G
  D --> G
  • Product loss is commercial and abrupt: a vendor announces end-of-support, stops selling licences, or goes out of business. The toolchain freezes at its last released version.
  • Environment loss is gradual and OS-driven: the platform the binary runs on is updated, deprecated, or replaced. The runtime may persist longer than the toolchain (Microsoft ships the VB6 runtime in Windows for the OS lifetime, but withdrew the VB6 IDE in 2008).
  • People loss is demographic and irreversible: developers age out of the workforce, and knowledge isn’t replenished because new entrants learn the currently-marketed stack, not the legacy one.

The dangerous phase is when these axes desynchronise. The runtime still ships, but the toolchain is gone and the maintainers have retired — exactly your VB6 position. You can run the code but cannot safely evolve it.


Generational timeline

Each wave of platform technology produced a cohort of business-critical code that later entered a sustainment gap. The pattern repeats roughly every 15–20 years — long enough for a generation of developers to build careers on a stack, retire, and leave the code behind.

timeline
  title Five generations of code entering the sustainment gap
  1959 : COBOL
        : Mainframe batch processing era begins
  1970s : COBOL dominates banking, government, insurance
  1991 : PowerBuilder
        : Client/server RAD era begins
  1995 : Delphi, VB6 era
        : Windows desktop business apps explode
  1998 : VB6 final release
        : Delphi and PowerBuilder mature
  2008 : VB6 IDE support withdrawn
        : Product loss for VB6
  2010 : SAP acquires Sybase / PowerBuilder
        : PowerBuilder enters vendor limbo
  2015 : Visual FoxPro end of support
        : Microsoft withdraws
  2020 : Flash / ActionScript EOL
        : Browser plugin era ends
  2025 : COBOL avg developer age 55
        : VB6 IDE unsupported for 17 years
        : PowerBuilder revived by Appeon
  2030 : Windows 10/11 VB6 runtime EOL
        : Environment loss closes the gap for VB6

Generation 1 — Mainframe batch (COBOL, 1959–)

FactorState
Code~43% of global banking systems; 95% of ATM transactions process through COBOL; $3T in running systems
ProductStill supported — IBM Enterprise COBOL 6.5 released June 2025. The compiler is alive.
EnvironmentMainframe (z/OS) persists; IBM continues investing. Runtime is not the problem.
PeopleAverage COBOL developer age ~55; ~10% of workforce retiring annually; almost no new entrants.
Gap driverPeople loss only. Product and environment are healthy. This is the purest demographic-cliff case.
StatusThe canonical slow-motion crisis. $105B/year in inefficiencies; 80% of legacy-agency IT budgets consumed just keeping systems running.

Generation 2 — Client/server RAD (PowerBuilder, Delphi, 1991–)

FactorState
CodeThousands of enterprise CRUD/ERP apps in government, insurance, banking, education, manufacturing.
ProductPowerBuilder orphaned by SAP (2010–2016), then revived by Appeon (PowerBuilder 2025 released May 2025). Delphi still sold by Embarcadero but 1.8% developer proficiency (2025 SO survey).
EnvironmentWindows desktop. BDE deprecated ~2000, breaks on W10/11 updates.
People1.8% Delphi proficiency; experienced practitioners approaching retirement.
Gap driverProduct + People. PowerBuilder survived via vendor transfer (Appeon); Delphi is commercially alive but demographically terminal.
StatusManageable for PowerBuilder (active vendor, migration path to C#/.NET via Appeon). Critical for Delphi (commercial tool exists, no workforce to use it).

Generation 3 — Windows desktop (VB6, 1998–)

FactorState
CodeExtensive enterprise codebases; exact volume untracked but vast. Your situation.
ProductIDE unsupported since 2008 — 18 years. No vendor will revive it. The toolchain is frozen.
EnvironmentRuntime supported in Windows 10/11 for the OS lifetime (~2030). Runtime is healthy; toolchain is dead.
PeopleOriginal maintainers retired or retiring — your stated situation. New entrants effectively zero.
Gap driverAll three axes simultaneously. Product lost (2008), people leaving (now), environment closing (~2030). This is the most advanced gap in the set.
StatusThe runtime buys time but the ability to rebuild from source is the immediate casualty. The window between “can still run” and “can no longer rebuild” is closing.

Generation 4 — Web plugin (Flash / ActionScript, 1996–2020)

FactorState
CodeE-learning, rich media, games, enterprise dashboards.
ProductAdobe Flash Player EOL December 2020. Content blocked from running.
EnvironmentBrowser vendors removed plugin APIs entirely. The execution environment was destroyed, not just the toolchain.
PeopleActionScript developers migrated to JavaScript/TypeScript; the language has no remaining practitioner base.
Gap driverTotal loss — all three axes collapsed simultaneously and irreversibly. The runtime was actively removed, not merely deprecated.
StatusThe cautionary tale. When environment loss is active removal rather than passive deprecation, there is no sustainment — only migration or abandonment.

Generation 5 — Current (Java/.NET/JS, 2000s–)

FactorState
CodeThe bulk of today’s enterprise systems.
ProductSupported, but LTS windows are shortening. Java 8 LTS extended repeatedly; .NET moves to 18-month LTS cycles. Old framework versions (e.g. .NET Framework 4.6.2) persist but are feature-frozen.
EnvironmentCloud-native shifts; containerisation; server OS lifecycles (Windows 10 EOL Oct 2025).
PeopleActive and large — for now.
Gap driverNot yet in a gap, but version-stratified. Code written against Java 8 or .NET Framework 4.x is already in a soft gap: the platform persists but the current tooling and workforce target newer versions.
StatusThis generation’s gap is being created now, in real time, through version churn rather than wholesale platform abandonment. The lesson: today’s supported stack is tomorrow’s legacy.

The generational pattern

Looking across all five generations, a clear pattern emerges:

flowchart LR
  Build["Build phase<br/>New stack<br/>Active product<br/>Young cohort"] --> Mature["Mature phase<br/>Widely deployed<br/>Stable product<br/>Mid-career cohort"]
  Mature --> ProductLoss["Product loss<br/>Vendor withdraws<br/>or moves on"]
  ProductLoss --> PeopleLoss["People loss<br/>Cohort retires<br/>No new entrants"]
  PeopleLoss --> EnvLoss["Environment loss<br/>Runtime deprecated<br/>or removed"]
  EnvLoss --> Gap["Sustainment gap<br/>Code still runs<br/>Cannot rebuild<br/>Cannot staff"]
  Gap --> Migrate["Migrate or abandon"]
  Gap --> Die["Lose the code"]
  Migrate --> Build
Build phaseNew stackActive productYoung cohortMature phaseWidely deployedStable productMid-career cohortProduct lossVendor withdrawsor moves onPeople lossCohort retiresNo new entrantsEnvironment lossRuntime deprecatedor removedSustainment gapCode still runsCannot rebuildCannot staffMigrate or abandonLose the code

Each generation follows the same arc: build → mature → product loss → people loss → environment loss → sustainment gap → migrate or lose. The cycle time is roughly 20–30 years from initial build to forced migration. The gap opens when any axis fails, but becomes critical when two or more fail simultaneously.

Key observations:

  • Runtime long outlives toolchain. In every Microsoft generation, the runtime ships for years after the IDE is withdrawn. This creates a false sense of security — the apps run, so the problem feels theoretical until the maintainers leave.
  • People loss is the slowest and most dangerous axis. COBOL proves this: the compiler is current, the mainframe persists, but the workforce is vanishing. You cannot train your way out of a demographic cliff in time.
  • Environment loss is the hard deadline. When the runtime is removed (Flash) rather than deprecated (VB6), there is no sustainment option — only migration.
  • Vendor transfer can rescue a product. PowerBuilder survived because Appeon took it from SAP. VB6 has no such rescuer because Microsoft will not license it to anyone. The difference between “orphaned” and “transferred” is often the difference between survival and loss.

Sustainment principles

From the pattern above, seven principles that apply to any generation — including whatever you migrate your VB6 code to next.

Principle 1 — Separate the three axes and track each independently

Sustainment decisions go wrong when “the code is fine” is used to mean “the runtime still runs.” Track each axis on its own clock:

  • Product health: Is the vendor still selling and supporting the compiler? Is there a migration successor? (VB6 IDE: no. COBOL compiler: yes. PowerBuilder: yes, via Appeon.)
  • Environment health: Does the target platform still ship the runtime? Is it deprecated or actively being removed? (VB6 runtime: ships until ~2030. Flash: removed in 2020.)
  • People health: How many people can build and debug this? What is their age distribution? Is the skill being taught anywhere?

When two of three axes are red, you are in the gap. When all three are red, you are out of time.

Principle 2 — Never let the toolchain be the single point of failure

If only one product can compile your code, and that product is unsupported, you cannot rebuild. This is the VB6 trap. Countermeasures:

  • Keep a buildable reference environment (the install instructions I gave you) documented and reproducible.
  • Prefer languages with multiple independent compilers (COBOL has IBM, Micro Focus, GnuCOBOL — three independent vendors). VB6 has exactly one (Microsoft, unsupported). twinBASIC gives you a second.
  • Decouple editing from compiling early (VS Code + command-line vb6.exe /make) so a toolchain failure doesn’t strand your source.

Principle 3 — Treat source code as the asset, not the binary

The binary is perishable; the source is the asset. But source without a working toolchain is an archive, not a codebase. Therefore:

  • Keep source in modern version control (git) with full history — not in the proprietary project format alone.
  • Keep build scripts reproducible and documented — the exact compiler switches, the exact environment, the exact dependency versions.
  • Periodically verify reproducibility: can a new machine build from source using only the repository and the documented toolchain? If not, you don’t have source — you have a fossil.

Principle 4 — Plan migration before the gap, not after

Every generation shows the same failure mode: organisations assumed the old stack “would eventually be replaced” and underinvested until forced. COBOL banks are the extreme case — they are now paying $105B/year for that assumption. The window for cheap migration is during the mature phase, when the toolchain still works and the people are still present. Once either is gone, migration cost multiplies.

  • Start a pilot on one module while the toolchain still works.
  • Benchmark conversion tools (twinBASIC, Mobilize VBUC) on real code, not samples.
  • Establish a target stack before the crisis, not during it.

Principle 5 — Prefer incremental over big-bang migration

The Strangler Fig pattern — replacing legacy components gradually while new functionality is built in the target stack — appears across every successful modernisation case (COBOL-to-Java, PowerBuilder-to-C#, Delphi-to-web). Full rewrites fail at a high rate because they attempt to re-derive decades of accumulated business logic in one move.

  • Migrate module by module, keeping the system running throughout.
  • Maintain a dual-stack period where old and new coexist — expensive but lower-risk than a cutover.
  • Sequence by risk and isolation: start with the most self-contained, lowest-business-criticality module.

Principle 6 — Capture the business logic before the people leave

The most valuable thing in legacy code is not the syntax — it is the encoded business knowledge that exists nowhere else. When the maintainers retire, that knowledge leaves with them. Code without people who understand it is archaeology, not engineering.

  • Document business rules in the code’s own comments, in a wiki, or in tests — written by the people who understand them, while they still can.
  • Record walkthroughs: have departing maintainers narrate the critical paths, data flows, and the “why” behind non-obvious decisions.
  • Write characterization tests (tests that document current behaviour) before migration, so you have a correctness oracle after the people are gone.

Principle 7 — Design the next stack for its own sustainment

The stack you migrate to will enter its own gap in 20–30 years. Build for that now:

  • Choose a platform with a long support horizon and multiple independent implementations (e.g. .NET has Microsoft + open-source runtime; Java has multiple vendors).
  • Prefer open standards over single-vendor lock-in for data formats and protocols.
  • Keep dependencies minimal and substitutable — every dependency is a future sustainment axis of its own.
  • Maintain build reproducibility from day one — the same principle that is failing you with VB6 now.

Applying this to the VB6 position

Your situation maps directly onto the framework:

quadrantChart
  title Where VB6 sits on the sustainment axes
  x-axis "Product healthy" --> "Product lost"
  y-axis "Environment healthy" --> "Environment closing"
  "COBOL 2025": [0.15, 0.20]
  "PowerBuilder 2025": [0.45, 0.40]
  "VB6 today (2026)": [0.90, 0.35]
  "VB6 ~2030": [0.95, 0.90]
  "Flash 2021": [0.95, 0.95]
Parse error on line 1:
quadrantChart  titl
^
Expecting 'NEWLINE', 'SPACE', 'GRAPH', got 'ALPHA'
  • Product axis (red): IDE unsupported 18 years. No vendor will revive it. This is your hardest constraint and the one you cannot fix — only route around (twinBASIC, or command-line vb6.exe /make from the installed kit).
  • People axis (red): your maintainers have retired. This is the slowest axis to recover and the one most often underestimated. Capture their knowledge now, from whoever remains, before it’s gone.
  • Environment axis (amber → red): runtime ships until ~2030. This is your clock. You have roughly 3–4 years before environment loss compounds the other two failures into a hard deadline.

Recommended priority order:

  1. People first — document business logic, record walkthroughs, write characterization tests while anyone who understands the code is still reachable.
  2. Toolchain second — establish a reproducible build (command-line vb6.exe /make + VS Code editing) so source is buildable independent of the IDE.
  3. Migration pilot third — run twinBASIC and Mobilize VBUC against one module to measure conversion cost before the clock forces a rushed decision.
  4. Incremental migration fourth — execute module by module into the target stack, using the Strangler Fig pattern, completing before ~2030.

The runtime gives you time. The retired maintainers do not. Sequence accordingly.

Comments

Leave a Reply