Object Pascal standards (Delphi and Free Pascal/Lazarus)
Criteria verified as of August 2026. Re-verify on the web before committing to anything (§8).
1. Scope and triggers
Object Pascal applications in production: maintenance, containment and exit. Two worlds that
share a language and almost nothing else — Delphi (Embarcadero, commercial, paid per developer) and
Free Pascal + Lazarus (free).
An honest statement of the domain, here and not hidden in §7: Delphi is not dead — there are recent
releases, with a new compiler for Windows on Arm and up-to-date Android support (§2) — but its
ecosystem has been shrinking for decades: market share is marginal, hiring is difficult
and expensive, the third-party component catalogue is full of abandoned pieces that whole
applications depend on, and the licence cost per developer is four figures a year (§2).
On the free side the diagnosis is different and equally uncomfortable: the latest stable version of Free
Pascal is 3.2.2, from May 2021, and Lazarus keeps publishing bugfixes built on top of it. It
is not abandonment — there is continuous activity — but the free compiler's release cadence is measured
in years, and that is a risk fact to put on the table before betting.
Translated into criteria: a Delphi application that works and does not grow gets maintained; one that grows
needs an explicit plan (§7). And starting a new project in Delphi is justified only if you already
have the team, the licences and a codebase to reuse — never by choosing it from scratch.
Covers: versions and licences of both chains, file types, VCL versus FMX, the Unicode
scar, data access, interoperability, and the decision to migrate, wrap or freeze.
Not applicable: see vb6-standards and classic-asp-standards (Microsoft legacy from the same
era: they share the "1990s desktop app that still bills" pattern, not the
platform — Delphi compiles natively, has a compiler and IDE with current support and a company
behind it charging for them; VB6 has none of the three. Do not extrapolate criteria between
them), dotnet-framework-legacy-standards (.NET Framework 4.x: the intermediate step in the Microsoft
world), dotnet-standards (the most common destination of a rewrite, and the owner of the
criteria for the resulting code — SDK, TFM, ASP.NET Core, EF Core, packaging — not this skill),
legacy-modernization-standards (theirs is the strategy — portfolio analysis, the decision to
invest/migrate/retire/freeze, sequencing, funding; here the technical criteria of this
platform and the facts that feed that decision), migration-projects-standards (theirs is the
execution of the cutover once decided: runbook, rehearsal, window, abort criteria, a rehearsed
rollback and decommissioning of the source system),
refactoring-tech-debt-standards (strangler fig, branch by abstraction, characterisation of untested
code), enterprise-architecture-standards (inventory, the TIME model),
testing-qa-standards (test strategy), cicd-standards (the pipeline),
git-workflow-standards (and especially handling binaries and generated files),
sql-standards and sqlserver-dba-standards/oracle-dba-standards/mysql-mariadb-dba-standards
(the engine behind FireDAC), api-design-standards (the contract of the service that wraps the
monolith), appsec-standards (threat modelling), vulnerability-management-standards,
opensource-licensing-standards (FPC's RTL static-linking exception is the fact that
decides whether you can distribute closed source, §2), windows-server-ad-standards,
vmware-standards/hyper-v-standards (the host of a frozen build machine),
backup-recovery-standards (the build machine and its third-party components are an asset to be
backed up), c-standards/cpp-standards (the other side of a native DLL).
2. Default decisions — versions, licence and cost
Verify on the web before pinning it in any document with consequences (§8).
| Decision |
Criterion |
Verified as of Aug 2026 |
| Commercial Delphi |
RAD Studio 13.1 "Florence" |
RAD Studio/Delphi/C++Builder 13 "Florence" shipped on 10 Sept 2025; 13.1 (Release 1) with an updated build on 18 Mar 2026. Relevant new features: a native Arm64EC Delphi compiler (Windows on Arm, Arm64EC ABI → mixing with existing x64 binaries), Android API 36.1 (required by Google Play from Aug 2026) and an LSP engine with LSIF |
| Cost per developer — the expensive fact |
Four figures per seat, and it is a named licence |
Starting prices for a new licence at a reseller (ComponentSource, Aug 2026): Professional ≈ USD 1,583, Enterprise ≈ USD 3,959, Architect ≈ USD 5,939. Named User (Workstation) model: one person, one machine, no concurrent use, valid only in the country of purchase (except for mobility within the EU). The subscription requires annual renewal to keep using the product. List and reseller prices differ: request a quote (§8) |
| Community Edition |
Fine for learning and for a micro-business; not for a company |
Free, a renewable 1-year licence, until the individual's or company's annual revenue reaches USD 5,000 or the team exceeds 5 developers. The threshold is on total revenue, not on what the app generates; a company billing more cannot use it, not even internally. It is not a trial version (there is a 30-day trial for that). There is no RAD Studio CE: only Delphi CE and C++Builder CE |
| Free Pascal |
FPC 3.2.2 — and that is the uncomfortable fact |
3.2.2 is from May 2021 and is still the stable release; 3.2.4 exists only as an RC (used for Lazarus's macOS builds). The project's site also warns that 3.2.2 is not available for every platform or format for lack of release builders and testers |
| Lazarus |
Lazarus 4.8 (bugfix) |
11 Jun 2026, "built with FPC 3.2.2, and FPC 3.2.4RC1 for macOS" (verbatim from the project's site). A healthy bugfix cadence, on top of a compiler whose stable release does not move |
| FPC/Lazarus licence |
It permits a closed product — but read it, do not assume |
The compiler and utilities are under the GPL; the RTL and the packages that end up inside your executable are under a modified LGPL with a static-linking exception, and that exception is what makes distributing proprietary binaries legal. Remaining obligations: state where the RTL source can be downloaded from, and publish your RTL modifications if you modified it. Legal advice for the specific case |
| Choosing between them |
Delphi if there is already a large VCL codebase, commercial components and budget; FPC/Lazarus if the criterion is zero cost, control of the chain or broad cross-compilation |
Source compatibility is good but not total ({$MODE DELPHI}/{$MODE OBJFPC}); the commercial visual components and the newer parts of Delphi's RTL do not port |
| Data access |
FireDAC. BDE vetoed |
Embarcadero's DocWiki: the BDE is deprecated and will not be improved — it will never have Unicode support —, no new development should use it and you must migrate to FireDAC. Since XE7 (2014) it is not even installed with the product. Assisted migration with reFind and the rules file FireDAC_Migrate_BDE.txt; aliases move from IDAPI.CFG to FDConnectionDefs.ini |
| VCL versus FMX |
VCL for Windows desktop; FMX only if there genuinely is cross-platform work |
They are not interchangeable: switching framework means rewriting the whole presentation layer. "We move it to FMX and it is cross-platform" is false and is the promise that has sunk the most projects in this domain |
3. Structure, conventions and the Unicode scar
- Files and what goes in Git:
.pas (unit), .dpr (program), .dpk (package), .dfm/.fmx
(form, save as text, never binary — otherwise reviewing diffs and merging
are impossible), .dproj/.groupproj (MSBuild project). In Lazarus: .lpr, .lpi, .lfm,
.lpk. Never in Git: .dcu, .ppu, .o, .exe, .bpl, .dproj.local, .identcache,
__history/, __recovery/ and the output directory.
- A reproducible command-line build, not one from the IDE:
msbuild over the
.dproj (or dcc32/dcc64 directly), lazbuild in Lazarus. A project that only builds with
the IDE open on somebody's machine does not have a build, it has a ritual. And search paths
are declared in the project, relative, not in each person's global IDE options.
- Delphi 2009's ANSI→Unicode migration is the scar that still splits projects. There
string
went from AnsiString to UnicodeString (UTF-16) and Char to 2 bytes. What still bites:
Length(S) is no longer bytes (everything that assumed 1 byte = 1 character is wrong: SizeOf(Char) or
TEncoding, never constants); PChar became PWideChar, so every call into the Windows API
or into a third-party DLL has to be reviewed one by one; and above all binary I/O and
persisted structures: writing a string to a file, socket or BLOB with pre-2009 code changes
the on-disk format — that is how this migration corrupts data, silently. Operational rule:
if the project has not crossed 2009, that is a project of its own, with characterisation over real
files and BLOBs, not a step inside another one; and explicit AnsiString/RawByteString with a declared
code page wherever the on-disk or on-the-wire format is bytes.
- No logic in the form: the business lives in units with no VCL dependency. That is what
makes testing possible (§4) and what decides whether a future migration is even conceivable. A
TForm of
8,000 lines with SQL inside is the domain's default pattern and it is the work to undo.
- Resources:
try..finally for every object created, always. And with interfaces, reference counting
acts on the interface, not on the variable declared as a class: mixing both
accesses to the same object is the classic leak.
- Third-party components: a written inventory with version, licence, source available yes/no and
maintenance status. A binary component with no source and no living vendor is a hard
limit on portability and on compiler version, and you need to know it before planning, not
during.
4. Quality, tests and CI
A deliberately short section: this ecosystem's tooling is limited and it is better not to pretend
otherwise.
- Tests: DUnitX in modern Delphi (
FPCUnit in Lazarus). A real precondition: the logic
must be outside the forms; what lives in the TForm is not testable without a GUI and will not
get tested.
- Compilation as a gate: a command-line build in CI, warnings and hints treated as
errors in your own code, and zero new warnings as a merge rule. It is the static
analysis you are guaranteed to have.
- Analysis and style: tools exist (IDE formatters, commercial analysers, and
on the free side
pas2js/FPC utilities), but the linter ecosystem is poor compared
with any mainstream stack. Do not plan quality relying on tools you will not
have: rely on review and on tests.
- Inherited code with no tests: characterisation first — capture real inputs and outputs
(files, reports, rows) and freeze them as a reference — before touching anything.
- §6 (Performance and operability) is omitted as artificial in this domain: there are no operability
decisions specific to Object Pascal that do not belong to the operating system, the data engine or the
deployment, and those already have owners. The only specific parts — the 32-bit process, the installer and
component registration — are covered in §7.
5. Stack security
- The real surface is three things: SQL by concatenation in old forms, binary
third-party components with no source and no patches, and the channel — a client-server
application talking to the database over the internal network without TLS.
- Always parameterised SQL (
TFDQuery.Params). Here injection does not arrive over the web: it arrives through a
field in a desktop form connected directly to the database.
- Credentials: out of the
.dfm, the executable and any plaintext .ini next to the .exe. And the
application does not connect with a shared privileged user — that inherited pattern is what
turns any failure into total compromise.
- Abandoned third-party components: there are no patches. If one handles a file format,
cryptography or a network protocol, it is a vulnerability with no fix date: wrap,
replace or isolate (
vulnerability-management-standards). No home-grown cryptography and no
encryption components from the 2000s (cryptography-pki-standards).
- Validation at the boundary, including configuration files and imports: a
TStringList.LoadFromFile over a file in a shared directory is untrusted input.
6. — omitted
See the note at the end of §4.
7. Migrate, wrap or freeze — and prohibitions
The three routes, with the criterion for choosing:
- Freeze. The app works, does not change and the business asks nothing of it. It gets armoured: a
reproducible command-line build, a build machine (with the IDE, licences and third-party
components installed) backed up as an image with a tested restore, dependencies
inventoried, and changes only for corrections or regulation. It is the right option more often
than people admit, and it is not surrender: it is ceasing to pay to evolve something that does not need it.
- Wrap. The app works but has to be integrated or given a new interface. The logic is exposed
as a service (HTTP/REST from Delphi itself, or a DLL/COM consumed from .NET) and everything
new is built outside against that contract — strangler fig, from
refactoring-tech-debt-standards. Precondition: the logic has to be outside the
forms (§3); if it is not, that is the first job, and it is the one that pays off for any
subsequent route.
- Migrate. Only when there is a real business reason (the Windows desktop no longer serves, there is nobody
to hire, the licence cost is unsustainable) and budget to rewrite the whole
presentation layer. Domain by domain, never all at once.
On automatic Delphi→.NET converters: they produce C# code with the structure of a
form-oriented Object Pascal program, with no idiom of the target and none of the equivalent
libraries. It is not a migration, it is a translation you then have to maintain. If it is used, it is as
scaffolding with a planned subsequent rewrite, and the result is governed by dotnet-standards.
Hard signals that you have to get out (not opinions, verifiable facts): the app depends on a
binary third-party component with no source whose vendor no longer exists; it only builds on one specific
machine that nobody knows how to reinstall; it is still 32-bit against a driver that no longer exists in 64-bit;
it has not crossed the Unicode barrier and internationalisation is needed; or nobody is left on staff who
knows how to maintain it and the cost of hiring exceeds the cost of rewriting.
Prohibitions:
- ❌ FORBIDDEN: new development with the BDE: deprecated by the vendor, with no Unicode and no
future (§2). Migrate to FireDAC.
- ❌ Saving
.dfm/.lfm in binary format.
- ❌ Committing
.dcu, .ppu, .exe, .bpl or __history/__recovery directories.
- ❌ Projects that only build from the IDE, or that depend on absolute paths and on one particular
developer's global IDE options.
- ❌ SQL by string concatenation; credentials in the
.dfm, in the binary or in a plaintext
.ini; a privileged database user shared by the application.
- ❌ Assuming
Length(S) is bytes, or persisting a string to a file/BLOB/socket without explicit
encoding (§3).
- ❌ Promising cross-platform by swapping VCL for FMX without budgeting the rewrite of the
presentation layer.
- ❌ Adding a third-party component with no source or with no living vendor to an application you
expect to maintain for more than two years.
- ❌ Putting new business logic into a
TForm.
- ❌ Automatic translation to C# presented as modernisation.
- ❌ Using Community Edition in a company billing more than USD 5,000 a year, even for
internal use or as a substitute for the trial: it breaches the licence (§2).
- ❌ Planning on licence prices taken from a blog: they are requested in writing (§8).
- ❌ Losing the build machine with no backed-up image and no tested restore.
8. Mandatory web verification
Before pinning anything in a real project, check on the web:
- The current RAD Studio/Delphi version (as of Aug 2026: 13.1 "Florence", with an updated build on
18 Mar 2026) and what it brings over the one you use.
- The real price per developer and the licence terms: the figures in §2 are reseller starting
prices (Professional ≈ USD 1,583, Enterprise ≈ USD 3,959, Architect ≈ USD 5,939)
and Embarcadero's list price and the volume/upgrade/academic ones differ. Declared
gap: request a written quote; do not plan with these figures. Also verify the
Named User nature, the country restriction and the annual renewal obligation.
- Community Edition eligibility in the current EULA: the revenue threshold (USD 5,000/year),
the 5-developer limit and the exclusions. The EULA overrides any summary.
- Support and end of life of Delphi versions: declared gap — Embarcadero does not publish
an EOL calendar comparable to other vendors'; support is tied to the current update
subscription. If you need a date for a plan, request it contractually.
- Free Pascal: whether 3.2.2 (May 2021) is still the stable release or 3.2.4/3.4 has shipped — it is the
health indicator of the free side. And Lazarus (as of Aug 2026: 4.8, 11 Jun 2026, on FPC
3.2.2 and FPC 3.2.4RC1 on macOS).
- The FPC/Lazarus licence read raw before distributing closed source: GPL for the compiler,
a modified LGPL with a static-linking exception for the RTL and packages, plus the obligation to
publish your RTL modifications. With
opensource-licensing-standards and legal advice.
- The status of every third-party component in the inventory: latest version, compatibility with your
Delphi version, licence, source availability and whether the vendor still exists. It is the
verification work that changes the plan most and the one that systematically does not get done.
- CVEs of the linked native libraries, of the database drivers and of the third-party
network/cryptography components.
- The status of
legacy-modernization-standards: the migration strategy is theirs — and the
execution of the cutover belongs to migration-projects-standards — and this skill only contributes the
platform's technical facts.
If the web contradicts this document, the web wins — flag the discrepancy.
1---2name: pascal-delphi-standards3description: Object Pascal in production - Embarcadero Delphi and Free Pascal/Lazarus, and the migrate/wrap/freeze decision. Use when working with .pas/.dpr/.dpk/.dfm/.fmx/.dproj/.groupproj Delphi files or .lpr/.lpi/.lfm/.lpk Lazarus files, the RAD Studio IDE and its Florence/Athens/Sydney/Berlin/Tokyo releases, dcc32/dcc64/msbuild command-line Delphi builds and .dcu/.bpl output, fpc and lazbuild, VCL versus FireMonkey/FMX, TForm/TDataModule/TComponent and published properties with RTTI, third-party VCL component packages and their .bpl runtime packages, string/AnsiString/UnicodeString/WideString and the Delphi 2009 Unicode break, PChar and PAnsiChar, ShortString, TStringList, BDE and IDAPI.CFG legacy data access, dbExpress, FireDAC with TFDQuery and FDConnectionDefs.ini, ADO/ODBC layers, exports and stdcall/cdecl DLL interop, COM/ActiveX with TypeLib, Delphi Community Edition eligibility and RAD Studio per-developer licensing cost, Lazarus LCL widgetset cross-compilation, or evaluating a Delphi codebase for rewrite to .N4---56# Object Pascal standards (Delphi and Free Pascal/Lazarus)78Criteria verified as of **August 2026**. Re-verify on the web before committing to anything (§8).910## 1. Scope and triggers1112**Object Pascal** applications in production: maintenance, containment and exit. Two worlds that13share a language and almost nothing else — **Delphi** (Embarcadero, commercial, paid per developer) and14**Free Pascal + Lazarus** (free).1516**An honest statement of the domain, here and not hidden in §7**: Delphi **is not dead** — there are recent17releases, with a new compiler for Windows on Arm and up-to-date Android support (§2) — but **its18ecosystem has been shrinking for decades**: market share is marginal, hiring is difficult19and expensive, the third-party component catalogue is full of abandoned pieces that whole20applications depend on, and **the licence cost per developer is four figures a year** (§2).21On the free side the diagnosis is different and equally uncomfortable: **the latest stable version of Free22Pascal is 3.2.2, from May 2021**, and Lazarus keeps publishing bugfixes built on top of it. It23is not abandonment — there is continuous activity — but **the free compiler's release cadence is measured24in years**, and that is a risk fact to put on the table before betting.2526Translated into criteria: **a Delphi application that works and does not grow gets maintained; one that grows27needs an explicit plan** (§7). And **starting a new project in Delphi is justified only if you already28have the team, the licences and a codebase to reuse** — never by choosing it from scratch.2930Covers: versions and licences of both chains, file types, VCL versus FMX, the Unicode31scar, data access, interoperability, and the decision to migrate, wrap or freeze.3233**Not applicable**: see `vb6-standards` and `classic-asp-standards` (**Microsoft legacy from the same34era**: they share the "1990s desktop app that still bills" pattern, **not the35platform** — Delphi compiles natively, has a compiler and IDE with current support and a company36behind it charging for them; VB6 has none of the three. **Do not extrapolate criteria between37them**), `dotnet-framework-legacy-standards` (.NET Framework 4.x: the intermediate step in the Microsoft38world), `dotnet-standards` (**the most common destination of a rewrite, and the owner of the39criteria for the resulting code** — SDK, TFM, ASP.NET Core, EF Core, packaging — **not this skill**),40`legacy-modernization-standards` (**theirs is the strategy** — portfolio analysis, the decision to41invest/migrate/retire/freeze, sequencing, funding; **here the technical criteria of this42platform and the facts that feed that decision**), `migration-projects-standards` (**theirs is the43execution of the cutover** once decided: runbook, rehearsal, window, abort criteria, a rehearsed44rollback and decommissioning of the source system),45`refactoring-tech-debt-standards` (*strangler fig*, branch by abstraction, characterisation of untested46code), `enterprise-architecture-standards` (inventory, the TIME model),47`testing-qa-standards` (test strategy), `cicd-standards` (the pipeline),48`git-workflow-standards` (**and especially handling binaries and generated files**),49`sql-standards` and `sqlserver-dba-standards`/`oracle-dba-standards`/`mysql-mariadb-dba-standards`50(the engine behind FireDAC), `api-design-standards` (the contract of the service that wraps the51monolith), `appsec-standards` (threat modelling), `vulnerability-management-standards`,52`opensource-licensing-standards` (**FPC's RTL static-linking exception is the fact that53decides whether you can distribute closed source**, §2), `windows-server-ad-standards`,54`vmware-standards`/`hyper-v-standards` (the host of a frozen build machine),55`backup-recovery-standards` (**the build machine and its third-party components are an asset to be56backed up**), `c-standards`/`cpp-standards` (the other side of a native DLL).5758## 2. Default decisions — versions, licence and cost5960> Verify on the web before pinning it in any document with consequences (§8).6162| Decision | Criterion | Verified as of Aug 2026 |63|---|---|---|64| Commercial Delphi | **RAD Studio 13.1 "Florence"** | RAD Studio/Delphi/C++Builder **13 "Florence"** shipped on **10 Sept 2025**; **13.1 (Release 1)** with an updated build on **18 Mar 2026**. Relevant new features: a **native Arm64EC Delphi compiler** (Windows on Arm, Arm64EC ABI → mixing with existing x64 binaries), **Android API 36.1** (required by Google Play from Aug 2026) and an LSP engine with LSIF |65| **Cost per developer — the expensive fact** | **Four figures per seat, and it is a named licence** | Starting prices for a **new licence** at a reseller (ComponentSource, Aug 2026): **Professional ≈ USD 1,583**, **Enterprise ≈ USD 3,959**, **Architect ≈ USD 5,939**. **Named User (Workstation)** model: one person, one machine, no concurrent use, **valid only in the country of purchase** (except for mobility within the EU). The subscription requires **annual renewal** to keep using the product. **List and reseller prices differ: request a quote (§8)** |66| Community Edition | **Fine for learning and for a micro-business; not for a company** | Free, a renewable 1-year licence, **until the individual's or company's annual revenue reaches USD 5,000** or the team exceeds **5 developers**. The threshold is on **total revenue**, not on what the app generates; a company billing more **cannot use it, not even internally**. **It is not a trial version** (there is a 30-day trial for that). **There is no RAD Studio CE**: only Delphi CE and C++Builder CE |67| Free Pascal | **FPC 3.2.2 — and that is the uncomfortable fact** | **3.2.2 is from May 2021** and is still the stable release; **3.2.4 exists only as an RC** (used for Lazarus's macOS builds). The project's site also warns that 3.2.2 is not available for every platform or format for lack of release builders and testers |68| Lazarus | **Lazarus 4.8** (bugfix) | **11 Jun 2026**, *"built with FPC 3.2.2, and FPC 3.2.4RC1 for macOS"* (verbatim from the project's site). A healthy bugfix cadence, on top of a compiler whose stable release does not move |69| FPC/Lazarus licence | **It permits a closed product — but read it, do not assume** | The **compiler and utilities are under the GPL**; the **RTL and the packages that end up inside your executable are under a modified LGPL with a static-linking exception**, and that exception is what makes distributing proprietary binaries legal. **Remaining obligations**: state where the RTL source can be downloaded from, and **publish your RTL modifications if you modified it**. Legal advice for the specific case |70| Choosing between them | **Delphi** if there is already a large VCL codebase, commercial components and budget; **FPC/Lazarus** if the criterion is zero cost, control of the chain or broad cross-compilation | Source compatibility is **good but not total** (`{$MODE DELPHI}`/`{$MODE OBJFPC}`); the commercial visual components and the newer parts of Delphi's RTL **do not port** |71| Data access | **FireDAC**. **BDE vetoed** | Embarcadero's DocWiki: the BDE **is deprecated and will not be improved** — *it will never have Unicode support* —, no new development should use it and you must migrate to FireDAC. Since XE7 (2014) it is not even installed with the product. Assisted migration with `reFind` and the rules file `FireDAC_Migrate_BDE.txt`; aliases move from `IDAPI.CFG` to `FDConnectionDefs.ini` |72| VCL versus FMX | **VCL** for Windows desktop; **FMX** only if there genuinely is cross-platform work | They are not interchangeable: switching framework **means rewriting the whole presentation layer**. "We move it to FMX and it is cross-platform" is false and is the promise that has sunk the most projects in this domain |7374## 3. Structure, conventions and the Unicode scar7576- **Files and what goes in Git**: `.pas` (unit), `.dpr` (program), `.dpk` (package), `.dfm`/`.fmx`77 (form, **save as text, never binary** — otherwise reviewing diffs and merging78 are impossible), `.dproj`/`.groupproj` (MSBuild project). In Lazarus: `.lpr`, `.lpi`, `.lfm`,79 `.lpk`. **Never in Git**: `.dcu`, `.ppu`, `.o`, `.exe`, `.bpl`, `.dproj.local`, `.identcache`,80 `__history/`, `__recovery/` and the output directory.81- **A reproducible command-line build**, not one from the IDE: `msbuild` over the82 `.dproj` (or `dcc32`/`dcc64` directly), `lazbuild` in Lazarus. **A project that only builds with83 the IDE open on somebody's machine does not have a build, it has a ritual.** And search paths84 are declared in the project, relative, not in each person's global IDE options.85- **Delphi 2009's ANSI→Unicode migration is the scar that still splits projects.** There `string`86 went from `AnsiString` to `UnicodeString` (UTF-16) and `Char` to 2 bytes. What still bites:87 **`Length(S)` is no longer bytes** (everything that assumed 1 byte = 1 character is wrong: `SizeOf(Char)` or88 `TEncoding`, never constants); **`PChar` became `PWideChar`**, so every call into the Windows API89 or into a third-party DLL has to be reviewed one by one; and above all **binary I/O and90 persisted structures**: writing a `string` to a file, socket or BLOB with pre-2009 code changes91 the on-disk format — **that is how this migration corrupts data, silently**. Operational rule:92 if the project has not crossed 2009, **that is a project of its own, with characterisation over real93 files and BLOBs**, not a step inside another one; and explicit `AnsiString`/`RawByteString` with a declared94 code page wherever the on-disk or on-the-wire format is bytes.95- **No logic in the form**: the business lives in units with no VCL dependency. That is what96 makes testing possible (§4) and what decides whether a future migration is even conceivable. A `TForm` of97 8,000 lines with SQL inside is the domain's default pattern and **it is the work to undo**.98- **Resources**: `try..finally` for every object created, always. And with interfaces, reference counting99 acts on the **interface**, not on the variable declared as a class: mixing both100 accesses to the same object is the classic leak.101- **Third-party components**: a written inventory with version, licence, source available yes/no and102 maintenance status. **A binary component with no source and no living vendor is a hard103 limit on portability and on compiler version**, and you need to know it before planning, not104 during.105106## 4. Quality, tests and CI107108A deliberately short section: this ecosystem's tooling is limited and it is better not to pretend109otherwise.110111- **Tests**: **DUnitX** in modern Delphi (`FPCUnit` in Lazarus). A real precondition: **the logic112 must be outside the forms**; what lives in the `TForm` is not testable without a GUI and will not113 get tested.114- **Compilation as a gate**: a command-line build in CI, **warnings and hints treated as115 errors** in your own code, and **zero new warnings** as a merge rule. It is the static116 analysis you are guaranteed to have.117- **Analysis and style**: tools exist (IDE formatters, commercial analysers, and118 on the free side `pas2js`/FPC utilities), but **the linter ecosystem is poor compared119 with any mainstream stack**. Do not plan quality relying on tools you will not120 have: rely on review and on tests.121- **Inherited code with no tests**: characterisation first — capture real inputs and outputs122 (files, reports, rows) and freeze them as a reference — before touching anything.123- **§6 (Performance and operability) is omitted as artificial** in this domain: there are no operability124 decisions specific to Object Pascal that do not belong to the operating system, the data engine or the125 deployment, and those already have owners. The only specific parts — the 32-bit process, the installer and126 component registration — are covered in §7.127128## 5. Stack security129130- **The real surface is three things**: **SQL by concatenation** in old forms, **binary131 third-party components with no source and no patches**, and the **channel** — a client-server132 application talking to the database over the internal network without TLS.133- **Always parameterised SQL** (`TFDQuery.Params`). Here injection does not arrive over the web: it arrives through a134 field in a desktop form connected directly to the database.135- **Credentials**: out of the `.dfm`, the executable and any plaintext `.ini` next to the `.exe`. **And the136 application does not connect with a shared privileged user** — that inherited pattern is what137 turns any failure into total compromise.138- **Abandoned third-party components**: there are no patches. If one handles a file format,139 cryptography or a network protocol, **it is a vulnerability with no fix date**: wrap,140 replace or isolate (`vulnerability-management-standards`). No home-grown cryptography and no141 encryption components from the 2000s (`cryptography-pki-standards`).142- **Validation at the boundary**, including configuration files and imports: a143 `TStringList.LoadFromFile` over a file in a shared directory is untrusted input.144145## 6. — omitted146147See the note at the end of §4.148149## 7. Migrate, wrap or freeze — and prohibitions150151**The three routes, with the criterion for choosing:**1521531. **Freeze**. The app works, does not change and the business asks nothing of it. It gets armoured: a154 reproducible command-line build, a build machine (with the IDE, licences and third-party155 components installed) **backed up as an image with a tested restore**, dependencies156 inventoried, and changes only for corrections or regulation. **It is the right option more often157 than people admit**, and it is not surrender: it is ceasing to pay to evolve something that does not need it.1582. **Wrap**. The app works but has to be integrated or given a new interface. The logic is exposed159 as a service (HTTP/REST from Delphi itself, or a DLL/COM consumed from .NET) and **everything160 new is built outside** against that contract — *strangler fig*, from161 `refactoring-tech-debt-standards`. **Precondition: the logic has to be outside the162 forms** (§3); if it is not, that is the first job, and it is the one that pays off for any163 subsequent route.1643. **Migrate**. Only when there is a real business reason (the Windows desktop no longer serves, there is nobody165 to hire, the licence cost is unsustainable) **and** budget to rewrite the whole166 presentation layer. **Domain by domain, never all at once.**167168**On automatic Delphi→.NET converters**: they produce C# code with the structure of a169form-oriented Object Pascal program, with no idiom of the target and none of the equivalent170libraries. **It is not a migration, it is a translation you then have to maintain.** If it is used, it is as171scaffolding with a planned subsequent rewrite, and the result is governed by `dotnet-standards`.172173**Hard signals that you have to get out** (not opinions, verifiable facts): the app depends on a174binary third-party component with no source whose vendor no longer exists; it only builds on one specific175machine that nobody knows how to reinstall; it is still 32-bit against a driver that no longer exists in 64-bit;176it has not crossed the Unicode barrier and internationalisation is needed; or **nobody is left on staff who177knows how to maintain it and the cost of hiring exceeds the cost of rewriting**.178179**Prohibitions:**180181- ❌ **FORBIDDEN**: new development with the **BDE**: deprecated by the vendor, with no Unicode and no182 future (§2). Migrate to FireDAC.183- ❌ Saving `.dfm`/`.lfm` in binary format.184- ❌ Committing `.dcu`, `.ppu`, `.exe`, `.bpl` or `__history`/`__recovery` directories.185- ❌ Projects that only build from the IDE, or that depend on absolute paths and on one particular186 developer's global IDE options.187- ❌ SQL by string concatenation; credentials in the `.dfm`, in the binary or in a plaintext188 `.ini`; a privileged database user shared by the application.189- ❌ Assuming `Length(S)` is bytes, or persisting a `string` to a file/BLOB/socket without explicit190 encoding (§3).191- ❌ Promising cross-platform by swapping VCL for FMX without budgeting the rewrite of the192 presentation layer.193- ❌ Adding a third-party component **with no source** or with no living vendor to an application you194 expect to maintain for more than two years.195- ❌ Putting new business logic into a `TForm`.196- ❌ Automatic translation to C# presented as modernisation.197- ❌ **Using Community Edition in a company billing more than USD 5,000 a year**, even for198 internal use or as a substitute for the trial: it breaches the licence (§2).199- ❌ Planning on licence prices taken from a blog: they are requested in writing (§8).200- ❌ Losing the build machine with no backed-up image and no tested restore.201202## 8. Mandatory web verification203204Before pinning anything in a real project, check on the web:2052061. **The current RAD Studio/Delphi version** (as of Aug 2026: **13.1 "Florence"**, with an updated build on207 18 Mar 2026) and what it brings over the one you use.2082. **The real price per developer and the licence terms**: the figures in §2 are **reseller starting209 prices** (Professional ≈ USD 1,583, Enterprise ≈ USD 3,959, Architect ≈ USD 5,939)210 and **Embarcadero's list price and the volume/upgrade/academic ones differ**. **Declared211 gap**: request a written quote; do not plan with these figures. Also verify the212 *Named User* nature, the country restriction and the **annual renewal obligation**.2133. **Community Edition eligibility** in the current EULA: the revenue threshold (USD 5,000/year),214 the 5-developer limit and the exclusions. **The EULA overrides any summary.**2154. **Support and end of life of Delphi versions**: **declared gap — Embarcadero does not publish216 an EOL calendar comparable to other vendors'**; support is tied to the current update217 subscription. If you need a date for a plan, request it contractually.2185. **Free Pascal**: whether **3.2.2 (May 2021)** is still the stable release or 3.2.4/3.4 has shipped — it is the219 health indicator of the free side. And **Lazarus** (as of Aug 2026: **4.8**, 11 Jun 2026, on FPC220 3.2.2 and FPC 3.2.4RC1 on macOS).2216. **The FPC/Lazarus licence read raw** before distributing closed source: GPL for the compiler,222 a **modified LGPL with a static-linking exception** for the RTL and packages, plus the obligation to223 publish your RTL modifications. With `opensource-licensing-standards` and legal advice.2247. **The status of every third-party component in the inventory**: latest version, compatibility with your225 Delphi version, licence, source availability and whether the vendor still exists. **It is the226 verification work that changes the plan most and the one that systematically does not get done.**2278. **CVEs** of the linked native libraries, of the database drivers and of the third-party228 network/cryptography components.2299. **The status of `legacy-modernization-standards`**: **the migration strategy is theirs** — and the230 execution of the cutover belongs to `migration-projects-standards` — and this skill only contributes the231 platform's technical facts.232233If the web contradicts this document, **the web wins** — flag the discrepancy.