The Seam Is Part of the System

A migration path is not evaluated inside the new language alone. This chapter examines the seam between a memory-safe component, the legacy code around it, and the organization that must operate both. The practical judgment is comparative: choose among new-project adoption, incremental replacement, and targeted work on high-risk components by asking which path fits the system’s performance, concurrency, interface, dependency, and capability constraints. No single language or strategy dominates across those conditions.

Three ways to change a living system

The least disruptive path is often to use a memory-safe language for a new project or a new component. There is no old internal contract to preserve, no accumulated ownership assumption to untangle, and no need to translate every historical design decision before the first release. The team can define the data model, failure behavior, and interfaces with the safer model in mind. This path is attractive when the organization has a continuing stream of new work and can support the language over the product’s life.

Its limitation is obvious: new-project adoption does not repair existing exposure. It changes the future flow of risk while leaving the current stock in place. It can also produce a false sense of progress if new components are chosen because they are convenient while an exposed legacy parser or service remains untouched. New development is a strong starting lane, not a complete legacy strategy.

Incremental component replacement addresses that gap. Instead of treating the old system as one indivisible object, the organization identifies a responsibility that can be separated behind an interface and replaces it while the rest remains in service. The candidate may be a feature, a service, or a processing component. The key requirement is not that it be small. It must have a responsibility that can be described and a boundary across which the old and new parts can exchange data with known meaning.

A third path targets high-risk components first. The guidance specifically identifies network-facing services, file parsers, codecs, and cryptographic operations as examples of areas where attack surface or operational importance can justify focused effort. These components may not be easy to change, but their risk may be too consequential to defer simply because the code is old or tightly coupled. Targeted work can include replacement, isolation, or a staged reduction of unsafe behavior, depending on what the system can support.

These paths are not mutually exclusive. A platform can require memory-safe languages for suitable new code, prepare an interface around a high-risk legacy service, and use compensating controls for a component whose dependencies cannot yet move. The choice is about sequencing and ownership. New-project adoption prevents more accumulation. Incremental replacement reduces selected historical exposure. High-risk targeting directs scarce effort toward consequences that matter most.

Language selection should follow this system decision, not precede it. The source identifies several constraints that can change the fit: low-level access and efficiency, highly concurrent workloads, the learning curve for developers, compatibility with existing code and third-party libraries, and the maturity of tools and community support.