WordPress Engineering

WooCommerce development, at the engineering layer

A store is a catalogue, a checkout and a set of integrations that all have to keep working under load. That is an engineering problem, and it is where most stores break — not in the theme.

The problem

Stores are judged on the checkout and break in the catalogue

WooCommerce will run a small store out of the box, and it will keep running one past the point where its defaults still fit. The catalogue grows into variations and attributes that were never designed; the checkout acquires plugins that each add a step; stock, tax and fulfilment have to reconcile with systems outside WordPress. Each of those is a decision, and the defaults are not decisions.

  • The catalogue has grown into variations nobody can manage consistently
  • Checkout has accumulated plugins and nobody can say what order they run in
  • The store is slow under load and fast when tested
  • Stock levels disagree between the store and a fulfilment or accounting system
  • Orders are being processed manually because the integration is incomplete
  • Product pages compete with their own category pages in search
  • A plugin update broke checkout and nobody noticed for a day
  • Discounts, tax or shipping rules have accumulated exceptions nobody can explain
Who this is for

The people who usually bring us this problem

A store that has outgrown its setup

It worked when there were two hundred products and the structure no longer fits.

A store with integrations that do not reconcile

Stock, orders or pricing disagree between systems and the gap is being managed by hand.

A store about to grow

It is adequate now and the traffic or catalogue growth being planned will not be.

What it costs

What this costs while it goes unfixed

Engineering faults are rarely confined to the engineering layer. These are the commercial consequences we see most often.

Catalogue structure is the decision that is hardest to change

Whether a product is a variation, a separate product, or a bundle determines its URL, its stock behaviour, how it is filtered and how it is priced. Deciding it wrongly is survivable at a hundred products and a migration at ten thousand — and the change touches every integration downstream of it.

Checkout is a sequence and plugins are not ordered

Every plugin that touches the cart or the checkout adds behaviour, and which one runs first is decided by priority numbers that nobody sets deliberately. A store with eight such plugins has a checkout whose behaviour is emergent, and the failure appears as an order that is wrong in one specific combination of circumstances.

Load exposes everything the catalogue hid

A store tested with one visitor at a time is not tested. Uncached product queries, session handling, stock checks on every page and a checkout that writes to several tables all behave differently with concurrency, and the difference is not visible in a development environment.

The store is one system among several

Stock, orders, pricing, tax and fulfilment frequently live somewhere else, and the store has to agree with them. An ecommerce site that is treated as a standalone WordPress installation develops data that only exists in one place, and the reconciliation is then a manual process nobody designed.

What we do about it

Capabilities

Each of these is work we carry out, not an area we advise on.

Catalogue and variation structure

Whether a product should be a variation, a separate product or a bundle; how attributes are used for filtering rather than for description; and how the structure maps to the URLs and the search behaviour the store needs.

Checkout and cart behaviour

The sequence of steps, which plugins act on it and in what order, what happens when a payment fails or a session expires, and how the store behaves for a returning customer with a saved cart. Designed rather than accumulated.

Performance under concurrency

What the store does when more than one person uses it: caching that respects cart and session state, query cost on catalogue pages, and the points where the store writes rather than reads. Measured with concurrency rather than with a single visitor.

Stock, pricing and tax

Where each of those is authoritative, how the store is kept in step with the system that owns it, and what happens when the two disagree. The rules a store has accumulated — discounts, tax exceptions, shipping bands — reviewed and expressed deliberately.

Payment and fulfilment integrations

Payment providers, fulfilment systems and the order lifecycle between them, with the same rigour as any other integration: what happens when the provider is unavailable, how a repeated notification is absorbed, and how an order's true state is established.

Order lifecycle and states

The states an order moves through, who or what moves it, and how a store's states map onto the fulfilment system's. Most order-processing problems are a mismatch between two state models that were never compared.

Product and category search behaviour

Product pages, category and attribute archives, filtered views and pagination, and how they relate in search. A store generates a very large number of URLs and the ones that should be findable is a decision rather than a default.

Custom functionality without plugin sprawl

Where a requirement needs code rather than a plugin, and where an existing plugin already does it correctly. Each plugin added to a store is a dependency with an update cycle, and the count is a design decision with a cost.

How we work

Engineering methodology

The sequence is deliberate. The order is usually what determines whether the work holds or has to be repeated.

  1. Establish the catalogue's real shape first

    How many products, how many variations, how they are structured and how they are filtered. The structure determines the URLs, the performance and the integration surface, and it is the decision that is hardest to revisit.

  2. Map the checkout rather than adding to it

    Every plugin that acts on the cart or the checkout, in the order it actually runs, with what each one does. The behaviour of a store's checkout is usually emergent, and it can only be reasoned about once it is written down.

  3. Measure with concurrency

    Not with one visitor. Catalogue pages, session handling and checkout writes behave differently under simultaneous load, and the constraint that matters is the one that appears at that point.

  4. Decide who owns stock, price and tax

    Per field, as with any integration. An ecommerce store is almost never the system of record for all three, and treating it as though it were is how stock and prices diverge.

  5. Treat the order lifecycle as a design

    The store's states, the fulfilment system's states, and the mapping between them, written down. Orders that appear stuck are almost always the result of two state models that were never compared.

  6. Count the plugins and say what each is for

    Every store accumulates them. Each is a dependency with an update cycle and a checkout-order position, and where two overlap the recommendation is usually removal rather than configuration.

Deliverables

What an engagement produces

Documentation is a deliverable, not an afterthought. On most of these engagements a large part of the value is a defect report precise enough for another team to act on.

Assessment

  • Catalogue shape: products, variations, attributes and how they are filtered
  • Every plugin acting on the cart or checkout, and the order they run in
  • Where stock, price and tax are authoritative
  • The order lifecycle on both sides, and where the two state models differ
  • Performance measured under concurrency rather than sequentially
  • Which URLs the store generates and which are meant to be findable

Build

  • Catalogue and variation structure corrected, with the migration it needs
  • Checkout sequence made deliberate rather than emergent
  • Integrations with defined failure behaviour and idempotent writes
  • Order lifecycle mapped between the store and fulfilment
  • Caching and query work for concurrency
  • Custom functionality where it is warranted, and plugin removal where it is not

Handover

  • What the catalogue structure is, and what changing it would involve
  • The checkout's actual sequence, and what each plugin contributes
  • Which system owns which field
  • What is monitored, and what a stuck order looks like
  • What the store does not do, stated plainly
Under the hood

Architecture and technology

What a store's engineering consists of

  • A catalogue structure that maps to how the products are actually sold
  • A checkout whose sequence is known and deliberate
  • Caching that respects cart and session state
  • Stock, price and tax with a declared owner per field
  • Payment and fulfilment integrations with defined failure behaviour
  • An order lifecycle mapped between the store and the systems around it
  • A deliberate answer to which of its many URLs should be findable

Why stores break under load

  • Catalogue queries uncached and repeated on every request
  • Cart and session data defeating page caching entirely
  • Stock checks performed on pages that only display products
  • A checkout that writes to several tables without a transaction
  • Third-party scripts in the checkout, blocking and failing independently
  • Caching configured for a store tested one visitor at a time
Adjacent problems

If this is not quite your problem

These overlap at the edges. Sending you to the right page is more useful than having you work it out.

The store has to talk to other systems

Authentication, mapping, failure handling and reconciliation.

WordPress API integrations

The store is slow generally

WordPress performance work, including the database underneath.

WordPress speed optimisation

The store needs its own functionality

Bespoke code where no plugin does what is required.

Custom WordPress plugin development

The catalogue's URLs need managing

Technical SEO for a WordPress estate, including filtered archives.

WordPress technical SEO
Questions

Frequently asked

Do you have ecommerce results you can share?

No, and we will not present one. There is no ecommerce engagement in our published work, and the page carries no sales, revenue or conversion figures — not because they would be unhelpful but because there are none to report. What it covers is the engineering: catalogue structure, checkout sequence, behaviour under concurrency, and the integrations a store depends on. Those are the decisions a store owner has to make, and none of them needs a sales number to be worth discussing.

Should our products be variations or separate products?

It depends on how they are sold, and it is the decision in a store that is hardest to change later. A variation suits products that differ by size, colour or similar attributes while sharing a description and a category. A separate product suits items that are genuinely distinct — different specifications, different categories, or sold independently in search. The choice determines the URLs, the stock behaviour, how the catalogue filters and how the integrations see the product, which is why it is decided against how the products are actually sold rather than against the admin being tidier.

Why is our store slow only sometimes?

Because it is tested one visitor at a time and used by many. Concurrency is where a store's real behaviour appears: cart and session data defeats page caching, stock checks run on pages that only display products, and a checkout writing to several tables behaves differently under simultaneous orders. A single-visitor measurement is compatible with a store that falls over at ten — the constraint is only visible at the point it becomes one, which is why the assessment measures with concurrency rather than sequentially.

We have a lot of checkout plugins. Is that a problem?

It is a risk rather than a problem, and the risk is that the order they run in was never decided. Each plugin that touches the cart or the checkout registers a priority, and where eight of them overlap, the resulting behaviour is emergent — which is fine until a specific combination of circumstances produces an order that is wrong. Mapping what actually runs, in what order, and what each contributes is usually the first piece of work, and it frequently ends with two of them being removed rather than configured.

How do we keep stock accurate?

By deciding which system owns it and making the other follow. A store that treats WooCommerce as the system of record while a fulfilment or accounting system also edits stock will always diverge, and the divergence is then managed by hand. The decision is per field — stock, price and tax are frequently owned by different systems — and the integration then carries the same requirements as any other: defined failure behaviour, safe-to-repeat writes, and a reconciliation that can establish whether the two agree.

Bring us the problem you have not been able to fix

Describe what is happening rather than what you think the cause is. If we are not the right people for it, we will say so.