Selected work

Platform architecture

When AI Accelerated Development, Architecture Became the Bottleneck

AI-assisted development made it easier for a logistics business to turn operational knowledge into working applications. My role was to help those independently useful products operate as one coherent platform.

Role
Lead Software Engineer
Scope
Customer, administration, pricing, and transport workflows connected through a shared platform API

A faster way to create software

The business had developed an unusual advantage: operational knowledge could become working software quickly through AI-assisted development. Ideas no longer had to wait for a conventional delivery cycle before they could be tried inside the business.

Useful applications emerged around customer quoting, administration, pricing, and transport operations. Each one reflected real workflows and could evolve around the people using it.

Software creation was getting easier. Keeping the resulting systems coherent was becoming the harder job.

When coherence became the constraint

As the application estate grew, each product also began developing its own backend routes, data access, integrations, and interpretation of shared rules. That was manageable while the workflows remained isolated. It became risky when the same transaction crossed several products.

A single freight transaction can involve identity, organisation pricing, shipment details, carrier selection, insurance, payments, booking state, communication, and downstream operations. Those decisions must agree even when users enter the workflow through different applications.

Duplicated decisions

Pricing, permissions, and customer context could be interpreted differently depending on the application handling them.

Unclear authority

Values moving between interfaces risked becoming trusted facts without one system owning the consequential decision.

The problem was not that multiple applications existed. It was that the platform lacked an explicit answer to a basic question: which system owns each business decision?

A shared platform boundary

I shaped the architectural response around a shared API that acts as the business backbone for the application estate. Rather than centralising every screen or workflow, it centralises the capabilities that need one authoritative implementation.

Platform boundary

Customer + operational applicationsShared capability APIBusiness rules + providers

The API follows a feature-driven modular-monolith structure. Transactional domains have explicit boundaries between routes, services, domain models, persistence, and provider adapters. Smaller capabilities remain pragmatic rather than inheriting ceremony they do not need.

A modular monolith was deliberate. The business needed clearer ownership and stable contracts—not the operational cost of premature microservices.

Defining business authority

The most important change was not moving endpoints. It was deciding which inputs could be trusted and where the final decision belonged.

Pricing

Applications submit shipment facts, not authoritative totals. Customer context, organisation rates, service eligibility, surcharges, margins, and rounding are resolved behind the shared platform boundary.

Booking and payment

Selected services are tied back to persisted quotes. Payable amounts come from trusted server-side state rather than totals calculated by a browser. Repeated commands use stable request identity so retries do not quietly become duplicate financial actions.

Permissions

Customer, staff, system, and capability-link access are treated as different actor models. Permissions are enforced at the API boundary, not inferred from whether an interface happens to display a control.

Evolving without a rewrite

The platform could not pause while its architecture changed. Existing customer journeys, operational tools, and provider integrations still needed to behave consistently.

I used a capability-by-capability migration pattern:

  1. Map the current owners and callers of a business capability.
  2. Define its authoritative boundary and contract.
  3. Implement that capability behind the shared API.
  4. Use compatibility adapters where an existing interface cannot move immediately.
  5. Compare behavior and protect critical invariants before retiring old ownership.

This keeps migration grounded in product and operational continuity rather than treating it as a route-for-route code move.

What changed in the engineering work

AI-assisted development did not make architecture less relevant. It changed where the difficult work sat.

When implementation becomes easier, more of the value moves into deciding where authority belongs, which rules must remain consistent, how retries and partial failures behave, and how independently useful applications continue operating as one platform.

The goal was never to slow down business-led software creation. It was to give that capability boundaries it could keep building against.