Many companies have operated stable Delphi applications for years or decades that model the core of their processes: order processing, production, service, logistics, billing, device management, document workflows. These systems contain not only code but a resilient interplay of business rules, data model, user guidance and operational experience. That is precisely what makes modernization demanding: the real value rarely lies in the UI, but in the evolved domain logic.
If modernization is understood as „rebuild from scratch“, loss is inevitable. Not because new technologies are per se bad, but because implicit knowledge in the legacy—edge cases, historical data, process exceptions, regulatory details—is often not fully reconstructed during the migration. The result are costly regression errors, altered process times, acceptance problems and a project that runs longer than planned.
Delphi can, however, be modernized very well without losing domain logic. The key is a controlled, incremental approach: first create transparency (architecture, data, risks), then decouple (UI, data access, domain logic), then modernize (database drivers, Unicode/64-bit, APIs, services, multiplatform) — and secure ongoing operation throughout. This article describes practical modernization patterns, typical pitfalls and an approach that works in B2B environments with high process criticality.
Why Delphi modernization is rarely a „technical project“
In reality modernizations fail not because of a missing compiler flag, but because of incorrect assumptions about system behavior. Delphi applications that have been extended over years often contain:
- Business rules in GUI events (OnClick, OnExit, OnValidate), often distributed across many Forms
- SQL statements „close to the surface“ and optimized for exactly one database over years
- Workarounds for historical data, edge cases, customer variants or tenant logic
- Batch processes that in practice run at fixed times and have dependencies
- Integrations into ERP, DMS, CRM or machines that are barely documented
- Tacit knowledge in the form of operational routines: „If error X, then check Y first“
Anyone who starts here with a big‑bang rewrite must recreate all that knowledge — including the mistakes the old solution no longer makes. The better approach is to treat the domain logic as an asset: first isolate, then secure, then modernize.
Modernization without losing domain logic: target vision and guiding principles
A viable target vision for B2B systems is not „everything new“ but an architecture that enables change. Typical characteristics:
- Separated responsibilities (UI, domain/business logic, data access, integrations)
- Testability and measurability (regression tests, logging, monitoring, reproducible builds)
- Incremental replaceability (modernize the UI without immediately rebuilding the data model; migrate the DB without rewriting the UI)
- API capability (REST-Server or a service layer to connect portals, mobile and integrations)
- Operational capability (Windows and Linux-Services, clear deployments, rollback strategy)
In Delphi this is particularly achievable because you can reuse existing Units and domain classes while modernizing around them: data access from BDE to BDE-replacement with native binding, new REST endpoints, new UI modules, new deployments.
Inventory: what must actually be preserved?
Before code is „touched“, a structured inventory is worthwhile. The goal is not full documentation, but a reliable basis for decisions.
1) Domain logic map instead of a code‑reading marathon
A domain logic map with the following perspectives has proven practical:
- Use cases: Which core processes are business‑critical? (e.g. create order, invoice, cancellation, return delivery, machine service, maintenance contract)
- Rules: Which validations, calculations, state machines exist?
- Variants: Tenants, customer configurations, country‑specific rules
- Interfaces: Import/export, ERP/DMS/CRM, devices/protocols
- Batch/Jobs: nightly runs, reports, data reconciliations
From this map emerge prioritized modernization packages: what must remain stable, what may change, what can follow later.
2) Make technical debt visible
Typical technical debt in older Delphi systems:
- Borland BDE/Paradox dependencies
- ANSI strings / missing Unicode migration
- 32‑bit only, outdated third‑party components
- Monolithic form logic, global variables, units with side effects
- Unclear transaction boundaries and „SQL everywhere“
The skill is not to dogmatically „clean up“ these points but to order them in a way that minimizes risk and maximizes business value.
Architecture decoupling: the lever against logic loss
The most frequent cause of logic loss is the mixing of UI, data access and business rules. Modernization therefore starts with decoupling — not with a „new UI framework“.
Layer-3 architecture as a pragmatic target state
For many Delphi legacy applications a Layer-3 architecture works well:
- Presentation Layer: VCL/FMX Forms, ViewModels/Presenters, validation only UI‑near (format, required fields)
- Business Layer: domain models, services, rules, state logic, calculations
- Data/Integration Layer: repositories, SQL/ORM parts, interface adapters, REST clients, messaging
The benefit: domain logic becomes testable and reusable. Later a customer portal, a REST-Server or an Linux service can use exactly the same domain services. This lets you modernize the „outer shell“ without reinventing the core logic.
Strangulation Pattern: progressively „embrace“ the old system
A proven migration pattern is the Strangulation Pattern: new functionality is implemented in the new structure (e.g. domain service + repository) while existing Forms are rebuilt step by step. The old world remains operational but is gradually replaced by the new one.
It is important to actively invert dependencies: not „Form calls SQL“ but „Form calls service“, and the service decides. This small inversion is often the greatest gain.
Modernizing data access: BDE replacement and FireDAC plan carefully
A central modernization step is the BDE replacement. Companies often underestimate that this is not just about drivers, but about SQL semantics, transactions, locking, data types and error behavior. Modern Delphi stacks typically rely on BDE-Ablosung mit nativer Anbindung with native drivers (e.g. for MariaDB/MySQL, PostgreSQL, SQL Server).
What really needs to be decided during the switch
- Database target: Will the existing DB remain? Is a database redesign sensible (e.g. from Paradox/Firebird to MariaDB or PostgreSQL)?
- Transaction model: Where do transactions begin/end? Which use cases must be atomic?
- Concurrency/locking: optimistic vs. pessimistic, handling deadlocks, retry strategies
- SQL dialect: date functions, string behavior, NULL handling, case sensitivity
- Performance: indexes, query plans, paging, batch inserts
Domain logic is tightly coupled to data behavior. If the data layer is migrated „on the side“ you risk subtle deviations in practice: rounding, sorting, date boundaries, lock conflicts. Therefore the data layer belongs early in the modernization plan, including migration path and test data strategy.
Pragmatic steps toward FireDAC migration
Instead of rebuilding the entire application in one go, the following sequence has proven effective:
- Introduce a data access layer (repository/DAO) as a facade
- Switch individual use cases to FireDAC (e.g. „read“ first, „write“ later)
- Unify connection handling, error handling, logging
- Gradually decommission BDE components where the facade is stable
This keeps the application continuously deliverable and avoids a prolonged period in which „everything is half done“.
Unicode, 64‑bit and dependencies: modernization pitfalls in detail
Many modernizations do not fail at concept level but on underestimated detail topics. Three of these are particularly common in Delphi projects.
Unicode migration: not just strings but data flows
In very old Delphi versions systems originate from an ANSI world. A Unicode migration then affects:
- String types and conversions (WideString/AnsiString/UnicodeString)
- File and path handling (Windows API, network paths)
- Import/export (CSV, fixed field lengths, EDI, legacy interfaces)
- Sorting/collation in the database
It is decisive to identify the critical data flows (e.g. invoice texts, product descriptions, international addresses) and set up regression tests for them. Unicode is less a „rebuild“ than a consistent quality process.
64‑bit migration: memory is not the only issue
The 64‑bit migration is often reduced to „pointer sizes“. In practice the issues are more often:
- Outdated third‑party components without 64‑bit support
- COM/ActiveX dependencies
- DLLs and drivers (barcode, devices, cryptography, signature)
- Installer/deployment and registry paths (WOW64)
A sensible strategy is first to inventory all external dependencies and define alternatives. Then the 64‑bit step becomes plannable — and not a surprise package shortly before release.
Windows 11 ARM64: check early instead of paying later
With Windows 11 ARM64 a new class of target systems appears. Even if not every company immediately needs native ARM64 builds, it is wise to check early:
- Are there native dependencies (DLLs, drivers) that do not run on ARM64?
- Does the application rely on emulation, and is that acceptable?
- How does the installer behave, how are update/repair handled?
In modernization projects this is a typical „late“ topic that becomes expensive. Better: include it early in the platform roadmap and resolve it technically.
REST-Server and services: making domain logic usable for portals and integration
Many companies do not modernize Delphi because the desktop app „looks old“, but because new requirements emerge: customer portal, partner access, mobile processes, integration with ERP/DMS/CRM, reporting pipelines. Clear interfaces are required for this. A REST server is often the most practical bridge.
API first? Only if rights and domain logic come along
An API is only an advantage if it enforces the same domain logic as the client. Otherwise two rule sets arise: one in the desktop, one in the backend. Consequences are inconsistencies and security gaps.
Therefore a REST server layer should sit as directly as possible on top of domain services. Typical building blocks:
- Authentication/authorization (roles, tenants, permissions)
- DTOs/serialization with clear versioning rules
- Transaction and error concept (HTTP status, problem details, logging)
- Idempotency and concurrency (for retries, queue processing)
This way the REST server becomes the stable integration point — not a „second client“.
Modernizing Linux services and Windows services
Batch processes and integrations run in many companies as Windows services, task scheduler jobs or even „hidden“ desktop instances. During modernization consolidation is worthwhile:
- Separate UI and background logic
- Configurable schedules and clear operational parameters
- Clean logging (structured logs, correlation per job/request)
- Option to run services under Linux (e.g. for containerized deployments)
The advantage is not only „modern“ but operational: reproducible operation, fewer manual interventions, better troubleshooting.
Modernize the UI without touching the core: VCL, FMX and hybrid approaches
Many modernization plans start with the UI. That can make sense — as long as it is clear what is gained. If the domain logic is decoupled, the UI can be renewed with significantly lower risk.
Modernize VCL applications step by step
VCL remains a robust choice in many B2B scenarios, particularly for Windows-heavy environments with high productivity on the desktop. Modernization can mean:
- Reduce UI logic (Presenter/ViewModel), move domain rules into services
- Clean up the component landscape, consolidate custom controls
- Improve responsiveness (async, background jobs, progress, cancel)
- Accessible operation, consistent validation, clearer error messages
This yields tangible benefits without rewriting the entire surface.
Delphi multiplatform: when FMX makes sense
If true multiplatform requirements exist (Windows, macOS, possibly Linux in a service context), FMX can be an option. The decisive factor is the expectation: multiplatform adds test and integration effort (fonts, printing, OS dialogs, file system, packaging/deployment). The costs are well calculable when the domain logic already resides in a clean layer.
A common pragmatic path is hybrid: VCL remains for the Windows client, while new frontends (portal, mobile app) are served via the REST server. This produces multiplatform capability across system boundaries, not via a single UI stack.
Testing and regression: how to pin down domain logic
„Losing domain logic“ means in practice: the system delivers different results in corner cases. This is rarely immediately visible but expensive. Therefore testability is not a luxury but a modernization tool.
Golden use cases and reference data
A proven approach is a set of „golden“ use cases: real, critical processes with defined data sets and expected results (e.g. the document chain from quote to credit note, or a maintenance order with spare parts and time bookings). These are established as regression tests or at least as repeatable test scripts.
Important: not only success paths but also typical error paths (lock conflicts, missing permissions, incomplete master data, duplicate import file).
Automate where it offers the greatest leverage
Not every legacy project needs 80% unit test coverage immediately. High ROI often arises in:
- Domain services (calculations, rules, state transitions)
- Data access with clear contracts (mapping, SQL, transactions)
- API tests (auth, permissions, versioning)
The objective is stability under change, not academic metrics.
Practical approach: a modernization roadmap in stages
From a B2B perspective modernization must remain deliverable. A typical roadmap that orients on risks:
Stage 1: Analysis, target architecture, quick wins (2–6 weeks)
- System map (modules, databases, interfaces, jobs, dependencies)
- Risk matrix (BDE, third parties, 32/64‑bit, Unicode, deployment)
- Definition of target architecture (Layer-3, service layer, API strategy)
- Quick wins: stabilize build process, improve logging, tidy version control
Stage 2: Decoupling domain logic (ongoing, incremental)
- Identify domain services and extract them from Forms
- Introduce repository facades
- First regression tests for critical use cases
Stage 3: Modernize data access / DB layer
- Introduce FireDAC, establish connection and transaction concept
- Module‑wise BDE replacement (or database migration with parallel operation)
- Test performance and locking behavior under load
Stage 4: Add REST server and integrations
- API with auth, permissions, versioning
- Connect portals/integrations without duplicating logic
- Consolidate services for batch and background processes
Stage 5: Platform and UI decisions (64‑bit, ARM64, multiplatform)
- 64‑bit build, replace dependencies
- Check/plan ARM64 compatibility
- UI modernization: VCL refresh or FMX/hybrid, based on business benefit
The order is deliberately chosen so you gain transparency early, then stabilize the core and only then roll out visible changes at scale. This reduces risk and keeps operations plannable.
Typical anti‑patterns: what makes modernizations unnecessarily expensive
Some patterns repeatedly appear in audits and rescue projects:
- „We rebuild and only adopt features“: almost always leads to logic loss because edge cases are missing.
- API as a parallel world: business rules remain in the client and are reinvented in the backend.
- Database change without semantic tests: same data, different behavior (NULL, sorting, date logic).
- Too late dependency management: 64‑bit/ARM64 fails on a small DLL shortly before go‑live.
- „Refactoring first“ without a target vision: many changes, little measurable benefit, high regression risk.
The counterproposal is always the same: first clarify the target architecture and risks, then rebuild incrementally while testing and making domain logic visible.
Conclusion: modernizing means preserving — and extending deliberately
Modernizing Delphi without losing domain logic is not a contradiction but a discipline. Companies do not need to choose between „keep everything“ and „replace everything“. With clean architectural separation (e.g. Layer-3), a controlled BDE replacement toward FireDAC, an API strategy via REST servers and a clear plan for Unicode, 64‑bit and new platforms such as Windows 11 ARM64 an evolved system can be migrated step by step into a future‑proof structure.
The decisive point is to treat domain logic as the core asset: isolate it, make it testable, then modernize. This creates an architecture that supports portals, services and multiplatform requirements without risking ongoing operations.
If you are planning a Delphi modernization and want to bring domain logic, data access and operations together cleanly, talk to us about a realistic migration path: https://net-base-software-gmbh.de/kontakt/