The starting point.

The web ERP was a live retail monolith built on SQL Server, C# and .NET Framework 4.8, Entity Framework, KnockoutJS, JavaScript, jQuery, Bootstrap and Crystal Reports. Reliability was a product requirement, not a maintenance footnote.

Its database had no migration system and was not owned by the web application alone. A much older VB6 desktop ERP and till application used the same schema, so a change that worked in the web path could still break daily work elsewhere.

The work covered new features, defects, stored procedures and views, reporting, two external courier integrations, requirements, training and support. Direct contact with the client was crucial for understanding how the software was actually used before changing it.

What the work had to respect.

The system could evolve only if old and new operational paths continued to agree:

  1. Existing workflows had to keep serving day-to-day retail work.
  2. SQL Server schema changes had to be backward-compatible because there was no migration history to coordinate every consumer.
  3. The .NET Framework web ERP and the older VB6 desktop and till applications shared the same database contract.
  4. KnockoutJS, jQuery, backend rules and database behaviour needed to change together when the web workflow changed.
  5. Requirements had to be checked with the client in operational language before they became code, reports or integration behaviour.
  6. Two external courier integrations had to remain understandable at the system boundary.

The diagnosis.

In a layered ERP, the visible delay or failure is often only the last link in the chain. A screen can be slow because of its request shape, backend work or a database access pattern. An integration issue can surface as a frontend inconsistency.

The shared database changed the usual definition of an internal implementation detail. Tables, columns and stored procedures were also contracts with VB6 software that could not follow a modern migration sequence.

I combined end-to-end tracing with direct client conversations. SQL Server queries and stored procedures, .NET Framework rules, KnockoutJS and jQuery screens, reports, courier exchanges and the legacy desktop path were treated as parts of one operational behaviour.

The working system view.

The useful unit of change was the whole operational contract: an action in the KnockoutJS and jQuery web interface, rules in .NET Framework 4.8, data work in the shared SQL Server schema, and the older VB6 desktop and till paths that depended on the same records. Reports and courier exchanges added further boundaries around that core.

The working system view. The web ERP and the older VB6 estate meet at one backward-compatible database contract.SYSTEM VIEW / ERPWEB OPERATORKNOCKOUT + JQUERY.NET FRAMEWORK 4.8SHARED SQL SERVERVB6 ERP + TILL
The web ERP and the older VB6 estate meet at one backward-compatible database contract.

Why continuity was an architectural choice.

This was evolution inside a live ERP estate, not a greenfield endorsement of its stack. The right technology decision was often to preserve an operational contract and improve it in place rather than make every layer new at once.

T01 The choice

Keep C#/.NET Framework and KnockoutJS for incremental change

Why
Features, defects and daily workflows already crossed these layers. Working within them allowed each change to follow the real request path and remain releasable alongside ongoing operations.
What I ruled out
A big-bang rewrite of backend and frontend would require the existing behaviour to be rediscovered and replaced before smaller operational improvements could reach users.
What it cost
The work accepts older framework constraints, mixed frontend patterns and continued maintenance knowledge instead of gaining a clean modern baseline immediately.
T02 The choice

Treat SQL Server as the shared data contract

Why
The web ERP, VB6 desktop ERP and till application read and wrote the same schema. Compatible SQL changes protected consumers that could not move with every web release.
What I ruled out
Migrating to a new database or schema as part of the web work would assume all consumers could cut over together despite the absence of a migration system.
What it cost
Additive changes and transitional structures can remain longer, and database design must account for old reads and writes as well as the new path.
T03 The choice

Evolve Crystal Reports and existing reporting paths

Why
Reporting was already part of the operational system and its SQL Server behaviour. Keeping that path in scope allowed report changes to be checked with the same data and application contract.
What I ruled out
Introducing a new reporting platform at the same time would add another migration and require existing report behaviour to be translated while application and database changes were still underway.
What it cost
The solution retains legacy reporting tooling and its design constraints, so report work continues to require specialised knowledge and cross-layer verification.
T04 The choice

Deliver one end-to-end workflow slice at a time

Why
A change could cover the operator screen, .NET rules, SQL behaviour and, when involved, reports, integrations and older consumers as one coherent operational slice.
What I ruled out
Modernising one technical layer at a time would leave behaviour divided between old and new paths and postpone proof that the real workflow still worked until several migrations were complete.
What it cost
Each slice must be completed and verified across every layer and consumer it touches, so progress demands disciplined boundaries rather than the visual uniformity of a layer-wide programme.

Rules for changing a live operation.

Stack continuity set the boundary; these rules kept each change connected to the full operating path and to the people using it.

D01

Trace the whole request path

Performance and reliability work starts with behaviour the client or operator can describe, then follows it through the web state, backend rules and database work instead of stopping at the first visible symptom.

The trade-offThis takes more investigation than patching the first slow component, but it avoids moving the bottleneck or fixing a symptom the client did not actually have.

D02

Make compatibility part of acceptance

A change is accepted only after it works through the web ERP and against the older desktop and till paths that share its records. Stored procedures, views, reports and courier exchanges join that check whenever the workflow touches them.

The trade-offThe acceptance surface is wider than the edited component, but a local success cannot quietly become a failure in another daily path.

D03

Define done in the client’s actual workflow

Client conversations translate a request into concrete workflows, edge cases and acceptance checks before the change. Delivery is complete only when the resulting behaviour reconnects to daily use, not merely when one component works in isolation.

The trade-offThis definition of done takes coordination time, but it is cheaper than shipping a technically coherent interpretation that does not fit the real retail process.

D04

Treat support and training as release feedback

Questions raised through support and training keep requirements tied to the way people understand and perform the work. That feedback informs the next bounded correction or improvement.

The trade-offDelivery responsibility extends beyond merging code, but usability gaps become visible while they can still shape the following release.

Delivery and verification.

Each change was checked at its layer and again through the operational workflow it supported. Stored procedures and views, .NET rules, courier responses, Crystal Reports and KnockoutJS state needed to agree.

Database work also required a compatibility question: what will the VB6 ERP and till application read or write after this change? Without migrations, that question had to be answered in the design rather than deferred to rollout automation.

Direct client feedback completed the check around everyday paths. A technically correct change was not finished if it made routine work harder to understand or no longer matched the operation described by the people using it.

The qualitative result.

The documented outcome was not a single modernisation launch. It was a series of bounded changes across application features and defects, SQL Server procedures and views, Crystal Reports, two courier integrations and stock-receipt workflows.

Each change was checked against the web path and, whenever it touched shared records, the database contract used by the VB6 desktop ERP and till application. This let the web ERP evolve without treating the shared schema as if it had only one consumer.

This case study does not claim a measured increase in performance or reliability. It records the delivery method used for the live estate: trace the operational workflow with the client, define compatibility at the affected boundaries and verify the complete slice before calling it finished.

What this case can prove

The organisation, product name, users, vendors, commercial data, operational KPIs and delivery dates are omitted. The technologies and integration boundaries come from the project record.