AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

A successful bulk insert does not prove data preservation

Django's PostgreSQL truncation fix shows why imports need explicit overlength handling and stored-value reconciliation, beyond a successful insert count.

Citiți articolul în română

An import can report success while storing less information than its source contained. Acceptance should therefore include an explicit policy for overlength values and a way to reconcile stored values with accepted input. An inserted-row count answers whether rows were created. It cannot, by itself, establish that every significant field survived unchanged.

The Django bugfix announcement of 6 January 2026 released 5.2.10 and 6.0.1. The 6.0.1 notes identify silent truncation of data exceeding max_length through PostgreSQL QuerySet.bulk_create(), introduced in Django 5.2. These historical patches provide a concrete example for the argument. They are not a recommendation to deploy those exact old versions in November 2026.

Keep the affected path precise

The 5.2.10 release notes confirm the same correction for that branch. For this regression, the affected released range runs from 5.2 through 5.2.9, plus 6.0; the fixed historical releases are 5.2.10 and 6.0.1. The condition concerns values exceeding their field limit on the affected PostgreSQL bulk-insert path. It is not a claim that every insert or every backend silently truncates.

Ticket 33647 distinguishes the bulk-create regression from an older bulk-update issue. Its discussion identifies PostgreSQL's UNNEST strategy and parameterized type casts as the relevant path. The January fix restores bulk-create behavior without establishing that every bulk-update truncation case was fixed too. A shared ticket title is a poor substitute for reading the actual correction's scope.

That distinction matters for incident review. An application that never used the affected path has a different question from an import using it with overlength strings. A system that uses both bulk creation and bulk updates has two paths to inspect. Copying a patch number into a ticket cannot establish which historical operations ran or what they stored.

Validation and insertion are separate responsibilities

An import contract should say what happens when a source value exceeds the destination's limit. Rejecting the row, isolating it for a decision and applying a documented normalization policy are different outcomes. Choose according to the meaning of the field. Silently accepting a shorter value as though it were the original obscures the decision from both operators and downstream users.

Consider an illustrative external reference used to match invoices. Removing its ending might destroy its ability to identify the original record, even if a destination row is successfully created. A free-text preview may permit deliberate shortening under a documented display rule. The difference comes from the field's purpose, not from whether the database accepted a statement.

Keep validation near the input boundary so that a rejection can identify the source row and field. The database remains an important enforcement layer, but an error message alone may not give a business operator enough context to repair a batch. Conversely, application validation is insufficient if another write path can bypass the same policy. The acceptance contract needs to cover the paths actually used.

Reconciliation examines values, not only totals

A proposed reconciliation can link each accepted source row to its destination and compare fields whose preservation matters. If normalization is intentional, compare against the agreed transformed value while retaining the original where policy permits. This provides a more useful acceptance question than whether the source and destination contain the same number of rows.

Counts remain useful. They can expose omissions or unexpected duplication. Their limitation is specific: equal counts can coexist with changed content. Likewise, a successful transaction says something about the database operation, but it does not explain whether the imported meaning matches the business requirement. Use each signal for the property it actually checks.

For large batches, choose a reconciliation strategy appropriate to risk and operating cost. Full field comparison may be justified for critical identifiers; other workloads may use carefully designed sampling and exception review. A sample cannot prove that every value was preserved. Record the coverage honestly rather than turning a practical check into a universal guarantee.

These are proposed operating practices. No local database, exploit or live import was run for this article. There is no measured discrepancy count, recovered dataset or claimed customer incident behind the examples. The release evidence establishes the historical bug and correction, while the import policy remains a design recommendation.

A patch prevents future behavior; it does not restore history

If an affected system accepted overlength input before correction, updating the framework does not reconstruct the missing suffixes. Recovery needs a trustworthy source or another retained record. An operator may have to reconcile historical imports, determine which values were altered and agree how to repair them. Those needs are conditional on evidence that the path and inputs were actually present.

Preserve source records and existing failure evidence while investigating. Re-running an import without understanding identity and duplication could introduce another problem. A recovery plan should distinguish finding a discrepancy, approving a replacement and applying it. The exact safeguards depend on the application's data model and responsibilities.

For a present deployment, select a currently maintained release compatible with the application and verify its relevant fixes. Historical patch availability helps reconstruct what was possible in January 2026. It does not establish the package installed in a particular environment, the state of an old import or the best version to run now.

Deliberate shortening can be legitimate

The strongest counterargument is a product that intentionally normalizes data before storage. Keeping a bounded preview or canonical representation can be entirely reasonable when the original meaning needed by the application is preserved elsewhere or the transformation is explicitly accepted. Byte-for-byte equality is then the wrong acceptance rule.

The requirement becomes clarity about the transformation. Identify which fields may change, who accepts that change and which original information remains available. For software maintenance, ask for both a visible overlength policy and reconciliation suited to that policy. Successful insertion is useful evidence; preservation requires asking about the values too.