Written by Robbert Nillessen, Software Architect.

Robbert Nillessen is a Software Architect focused on designing scalable and robust systems that integrate seamlessly with existing infrastructures.

In this article, Robbert shares his expertise in API development and integration, with practical insights into combining legacy and modern web applications.

Scope note: Robbert offers direct expertise in API development and integration, which is relevant to the topic of system integration and data source management.

Conflict resolution in legacy and web app integrations

When integrating legacy systems with modern web applications, such as those built with Laravel, it is crucial to define clear conflict resolution rules and a source of truth. This prevents data loss and operational inefficiencies.

  • Middleware, such as an Anti-Corruption Layer, prevents legacy structures from contaminating the modern application.
  • Without a clear source of truth, simultaneous changes can lead to data loss and inconsistent statuses.
  • Idempotency keys in API headers help prevent duplicate transactions during repeated requests.
  • Conflict rules must take into account the degree of simultaneous interactions and the chosen integration direction (bi- or uni-directional).
  • A lack of conflict rules can lead to a growing exception queue and increased need for manual checks.

The role of middleware and Laravel in legacy integrations

A modern Laravel domain model becomes contaminated as soon as it has to directly adopt the outdated data structures of a legacy system. Integration then shifts from a useful bridge to a dependency in which the new web app starts carrying the same limitations, naming conventions, and structural issues as the existing system.

In this context, middleware acts as a separation layer between both worlds. At its core is an Anti-Corruption Layer: an adapter layer that translates between the modern model in Laravel and the data structures of the legacy system. That translation does more than simply pass data through. It keeps the meaning of data on the Laravel side separate from how that data was historically recorded in the legacy system. As a result, the modern web app remains focused on its own domain model, while the integration can still connect to existing back-office logic.

Its practical value lies in consistency during integration. Without such an intermediate layer, the temptation becomes strong to let legacy structures reappear directly in the web app, because that seems faster in the short term. In practice, however, that creates confusion: a modern interface presents data that is still internally built according to old structures. This makes it harder to keep clear which system is authoritative for a given business object, because the web app does not truly have its own model but becomes a reflection of the legacy system.

Laravel is not just a technical framework here for building a custom web application, but also the place where that separation remains manageable. The framework provides room to set up a custom layer in which the modern domain model remains separate from the legacy side. The runtime sequence then becomes concrete: data comes in from the legacy system, the Anti-Corruption Layer translates it into the Laravel model, and only then does that information become usable in the web app. If that translation layer is missing, the legacy structure enters the application directly and the confusion about definitions and record meaning shifts from the integration to the daily workflow.

Why source of truth and conflict resolution are crucial

Simultaneous editing of the same record in the legacy system and the web application quickly breaks down into data loss as soon as it is not defined which system is authoritative and the last write automatically wins. Information from the first edit then disappears without the process itself stopping. For teams, the integration feels technically functional, while the actual status of customer data or orders has already started to diverge.

That makes source of truth not an abstract architecture concept but a direct operational boundary. As soon as two systems are allowed to update the same data without clear authority, there is no neutral middle ground: one change overwrites the other, or both systems show different versions of the same record. In a legacy integration with a modern web application, that ambiguity leads not only to discussion about which screen is correct, but also to extra verification work because employees have to determine which change is still reliable.

Conflict resolution should therefore not become visible only when records have already collided. Without predefined rules for what happens during simultaneous changes, the problem shifts into operations. Employees may see a status, but not whether that status is still current or has already been overtaken by another edit. This increases the chance that departments continue working from different information, even though the integration is officially active on paper.

The damage is not limited to inconsistent data at screen level. Inconsistent data statuses carry through into follow-up steps and can result in operational errors such as duplicate shipments or incorrect invoicing. That is exactly where the real pressure arises in organizations running a legacy system alongside a web application: not at the connection itself, but at the moment when the same reality is recorded differently in two systems and the wrong status is used as the starting point.

Problems caused by the absence of clear conflict rules

A legacy API timeout can cause a Laravel Job to be automatically retried, while the first request has already been partially or fully processed by the legacy system. Without clear conflict rules, this does not create a clean recovery action but a second processing of the same record. In a legacy integration, the technical connection then becomes detached from the operational truth: inventory levels or financial records diverge, while both systems appear to show a valid status.

That friction grows once it is not defined what should happen when two updates collide. Last-Write-Wins without warning then blindly overwrites earlier changes with the most recent update. At first glance, that seems simple, but in practice information disappears without any visible decision point. Teams may see a current status, but not that an earlier change has been wiped out. The result is that departments rely on different outcomes, even though the data comes from connected systems.

The operational problem lies not only in data loss, but in the moment when the deviation becomes visible. As long as the integration keeps processing messages, the process appears to continue. Only later does it become clear that records no longer match and that back-office teams and IT must manually determine which change should have been authoritative. This creates exactly the extra reconciliation pressure that quickly builds up around shared data objects: not one faulty record, but a growing stack of exceptions that must be assessed separately.

Missing conflict rules therefore make status propagation unreliable, even if the integration technically responds as designed. A retry can cause duplicate processing, a later update can overwrite an earlier one, and both events can appear as valid in different systems at the same time. For users, the boundary between current information and outdated information then disappears. The integration still works, but operational processes shift toward manual control because the exception queue grows faster than the systems themselves can explain.

Key factors in determining conflict rules

Simultaneous changes in both the web application and the legacy system make conflict rules an immediate operational design choice, because the same data is then affected from two sides and a technical integration by itself no longer indicates which system is authoritative at that moment.

Decision factorWhat this determines in the conflict rulesOperational risk if this remains unclear
Degree of simultaneous user interactionsWith a high degree of simultaneous interactions in both the modern web app and the legacy back office, conflict rules must explicitly define what happens as soon as both systems modify the same data object around the same time. This factor therefore determines not only whether conflict handling is needed, but also how strict those rules must be.Without that boundary, room emerges for contradictory process states. Teams may then see different versions of the same record and take diverging follow-up actions based on them, while the integration technically continues to run as normal.
Choice of bi-directional or uni-directional integrationA bi-directional integration gives both systems more room to write data back. As a result, conflict rules must cover more situations, because changes from two directions can intersect. In a uni-directional integration, that room is smaller and the number of possible conflict situations remains more limited as well.More flexibility without clear boundaries increases the risk of conflicts. In practice, the problem then shifts from technology to operations: employees no longer know which system should be followed, and correction work increases once data starts to diverge.
Authoritative system per data typeSource-of-truth design revolves around defining which system is authoritative for each data type. That choice directly drives the conflict rules, because only then is it clear which change takes precedence when the same information exists in both systems.If that authority is not defined per data type, it remains unclear during a conflict which version is reliable. This increases the chance that departments work from outdated or conflicting information and later have to manually repair what already went wrong during the process.
Difference between flexibility and conflict riskThe trade-off between maximum flexibility and lower conflict risk determines how much write freedom the integration gets. Conflict rules must therefore align with that choice: more flexibility requires sharper boundaries around what may be written back from which system, while less write traffic keeps the rule set more compact.If this trade-off remains implicit, a model often emerges in which both systems are allowed to change more than is operationally sustainable. That increases not only the chance of colliding updates, but also the confusion about process ownership once statuses begin to diverge.

A practical framework for conflict resolution in integrations

Repeated API requests after a network error can, without idempotency, directly cause duplicate transactions or inconsistent statuses in the legacy system, making conflict resolution visible only after records have already started to diverge.

  • Start with repeat behavior rather than the exception. In an integration between a legacy system and a web application, some conflicts arise not from substantive differences, but because the same request arrives again. This happens, for example, after a network error. A practical framework therefore starts with the question of which requests can be resent and which records may be affected as a result. Without that boundary, the integration appears to work technically, while the same change is later processed more than once.
  • Assign a fixed idempotency key to each change. The core of this step is that a repeated request remains recognizably the same request through an idempotency key in the API header. The integration layer then does not treat the second attempt as a new mutation. This shifts conflict resolution from manual recovery afterward to controlled recognition beforehand. In operational terms, this means teams are less likely to see two different outcomes for the same action in the web application and the legacy system.
  • Link the conflict rule to transactions and statuses. Duplicate processing affects not only a record, but also the status employees use to continue their work. If a repeated request is executed again, the same process step may be recorded twice or a status may change incorrectly. By treating idempotency as a fixed conflict rule for mutations that cause transactions or status changes, it remains clearer which result is valid. This limits confusion about which system appears authoritative at that moment, even if the technical connection is available.
  • Assess conflict resolution based on the recovery work it prevents. The practical effect of this approach lies in what no longer has to happen: fewer duplicate transactions, fewer inconsistent statuses, and less investigation when records diverge between systems. In organizations where a web application runs alongside a legacy system, this translates into less reconciliation and fewer moments when teams have to guess which record is correct. The framework is therefore not just a technical measure, but a way to limit operational errors before they enter the daily workflow.

Summary of conflict resolution and source of truth in integrations

Two systems that show the same information but do not carry the same meaning undermine the use of the web application even before a visible technical defect occurs. As soon as it is not explicitly defined which source of truth is authoritative, conflict resolution shifts from a design choice to daily interpretation work. What emerges is not a clear workflow, but a situation in which teams have to guess which status or record can still be trusted.

That ambiguity carries through into the structure of the integration itself. A modern web application placed alongside a legacy system without clear boundaries easily adopts terms, statuses, or record meanings that carry different weight in the old system. In that context, an Anti-Corruption Layer is not an extra layer added for technical complexity, but a boundary that prevents the modern model from being directly contaminated by legacy meanings. Without such a separation, conflicts do not remain limited to a single integration point; they spread to screens, process steps, and interpretations in daily operations.

The result usually does not first become visible in the integration itself, but in user behavior. If the information shown in the web application does not consistently align with what the legacy system represents, trust in the new environment declines. Users then fall back on the old system, double-check data, or bypass the web application in their work. As a result, the investment in a more modern way of working shifts into extra coordination, extra checks, and a greater chance of errors outside the system.

Conflict resolution and source of truth therefore belong to the same boundary: not only defining which system contains data, but which system carries meaning and authority once records can diverge. If that boundary is not consistently enforced between the legacy system and the web application, the new environment remains formally available but operationally suspect, with reduced adoption of the web application because users do not trust the information shown.

Sources