Skip to content

Front-End Scope, the AWS Outage & Migration, and Why Some Abstractions Exist

Mutual

V and Bruno’s engagement was front-end focused: a redesign of the homepage and the logged-in user experience. The brief was not a full-stack rebuild, and the original plan did not include infrastructure or disaster recovery work.

On March 1, 2026, drone strikes during the Iran conflict damaged Amazon Web Services data centers in the UAE and Bahrain, taking multiple availability zones offline across the region, including S3, the storage service this project depended on for assets. This was widely reported as the first known military strike on hyperscale cloud infrastructure, and it caused real, multi-day disruption for many companies running in that region, not just this project.

Because the project’s storage was in the affected region, V and Bruno stepped outside the original front-end scope to migrate the client to Digital Ocean and restore service, in order to keep the site operational. This was done as a goodwill measure, outside the original front-end contract, reactive, time-boxed work to prevent an outage from becoming a shutdown, not a planned infrastructure engagement.

Like many projects that have grown over several years and several contributors, the codebase includes a substantial amount of code unrelated to the pages V&B was engaged to redesign: additional assets, flows, and logic accumulated over time. In a couple of places, that made the new front-end work harder to land cleanly. For example, some flows needed extra handling to work correctly for logged-in (non-guest) users, and coupon logic wasn’t yet structured in a way that a new flow could call safely on its own.

Rather than rework those areas broadly, which was outside scope, V and Bruno added a small number of service-layer abstractions: focused, single-responsibility classes that sit alongside the existing code and give the new front-end flows a clean, specific way to use it, without requiring a wider rewrite.

Two examples from the codebase, both under app/Services/:

  • ValidateCouponService wraps coupon validation (existence, expiry, category applicability) behind a single validate() method, so that logic lives in one place rather than being repeated inline.
  • ApplyCouponService wraps discount calculation behind a single applyCoupon() method. It’s intentionally scoped to the new guest-order flow rather than acting as a single source of truth for every coupon-related path in the application, since consolidating all of those safely would be its own dedicated piece of work.

This pattern, a small, well-documented service sitting alongside existing logic rather than replacing it, let new front-end features ship without a wider rewrite, while giving future maintainers a clear, isolated entry point for the flows that were touched.

  • These service classes are scoped to the flows they were built for (e.g. guest checkout). Other parts of the application, the admin panel, vendor panel, and so on, may still call into the underlying logic directly, and weren’t part of this scope.
  • Continuing to consolidate coupon logic (and similar duplicated areas) behind a shared service, as time and priorities allow, would reduce the chance of the two paths drifting apart.