Caswell Software Advisory Ltd

Re-using code is easy, re-using assumptions is dangerous

2026-08-10T08:30:00.000Z

Good tests don’t prove your software works.

They prove it works under a particular set of assumptions.

One of the easiest mistakes in engineering is assuming that reusable APIs and reusable tests imply reusable confidence.

They don’t.

Tests only prove behaviour under the assumptions they were designed around. Change the workload, the failure model, or the definition of correctness, and those same tests may no longer prove what you think they do.

Earlier in my career I worked on a backup platform built around generic source and destination APIs. My team implemented and heavily tested file-system backups to multiple storage targets, including AWS S3 and Hitachi HCP.

Our automated tests exercised large data volumes, retries, resumptions and unreliable networks. Over time we built strong confidence that the platform was robust for file-system backup workloads.

The platform was later extended to support VMware virtual machine backups using the same abstractions and much of the same infrastructure.

At first glance this looked like a natural reuse problem:

But the correctness model had fundamentally changed.

With file-system backups, partial failure is often survivable. If one file fails to transfer, the rest of the backup may still be usable.

VM backups are different. A VM image is effectively atomic: if a single block is missing or corrupted, the entire backup may be unusable.

The APIs were reusable. The existing test assumptions were not.

As the VM capability evolved, the system was now operating under a different set of invariants and failure modes, particularly around integrity, ordering and restore behaviour under adverse conditions. In practice, however, existing test coverage was initially treated as sufficient.

The first customer deployment exposed the gap immediately.

The customer attempted to back up more than 50 large VMware virtual machines across a flaky WAN connection to a heavily utilised storage system. Under those conditions the platform encountered failure modes that were survivable for file-system backups but catastrophic for VM images: intermittent connectivity, partial transfers and repeated retries over long backup windows.

While the individual components behaved as designed, the resulting VM backups could not be relied upon for restore. After months of additional hardening and mitigation work, the customer ultimately abandoned the product.

Looking back, the issue wasn’t poor engineering or flawed abstractions. The platform did what it was designed to do.

The problem was more subtle: confidence earned under one set of correctness assumptions had been implicitly reused under another.

A reusable API does not imply a reusable definition of correctness.