Back to blog
Guides·Published onAug 6, 2025

Composable by Design: How Vendure Enables Plug-and-Play Custom Logic

HAS
Housein Abo ShaarGrowth Engineer & Developer Advocate, Vendure
In the dynamic world of e-commerce, flexibility isn't just a feature—it's a necessity. As business needs evolve, platforms must be able to adapt seamlessly. However, many platforms make this difficult, forcing developers to uproot entire implementations just to add custom logic. Our platform stands out by providing the deep, granular control over its core logic that enables true adaptability.

We'll look at how Vendure's design is used to solve common developer headaches and enable truly flexible e-commerce solutions.

The Challenge of Scaling Logic

In a growing application, simple code often becomes complex as requirements evolve.

Let’s take this over-simplified shipping calculator as an example: 

However, as the business grows, so do the requirements. Free shipping might be introduced for orders over a certain value. The function adapts with its first conditional check:

Later, additional rules are added—weight-based rates for international shipping, and eventually, integration with a third-party API for real-time rates. Each new requirement adds another layer of logic, and the once-simple function becomes exponentially more difficult to manage:

This growing complexity has a ripple effect on development:

  • Testing becomes time-consuming as the number of possible paths through the code increases.
  • Small changes risk breaking unrelated functionality, leading to bugs that are hard to track down.
  • Collaboration slows as multiple developers need to work on the same fragile piece of code.
  • Fear of regressions makes even minor updates feel risky.

Over time, this tightly coupled, condition-heavy logic becomes a bottleneck. It slows down development, makes adapting to new business needs harder, and creates frustration for the entire team.

Where Vendure stands out

This shipping calculator scenario highlights a critical architectural choice.

In many other platforms, core logic like this is deeply embedded. The logic is so tightly coupled that introducing a custom rule means you either have to find a clumsy workaround or, in the worst case, completely uproot the entire implementation and rebuild it from scratch. There are no clean "hooks" or "entry points" to inject your custom logic.

Vendure’s architecture is fundamentally different. It was built on the philosophy that you should never have to fight the platform as a developer. Instead of a rigid structure, Vendure provides a composable system similar to "lego blocks." This is made possible by embracing a design principle known as the Strategy Pattern, which suggests that instead of one monolithic function, each distinct piece of logic should be encapsulated in its own interchangeable 'strategy'.

Each strategy in Vendure is a dedicated entry point for your custom code. It’s a pre-defined hook where you can swap out Vendure’s default behaviour with your own.

Think of any part of an e-commerce system you might want to customise. Chances are, Vendure has a strategy for it:

  • OrderCodeStrategy: Need to generate order codes that match your accounting system? Just swap in your own "lego block" for this.
  • StockLocationStrategy: Want to decide which warehouse fulfils an order based on stock levels and proximity? Provide a custom strategy.
  • AssetStorageStrategy: Need to store product images in a specific cloud provider like Azure Blob Storage instead of the default? It's just a different strategy to plug in.
  • TaxLineCalculationStrategy: Is your tax logic incredibly complex? The Strategy Pattern isolates this complexity into its own manageable component.

This approach means you can surgically replace just the piece of logic you need to, leaving the rest of the stable, tested platform untouched.

From Code to Configuration: A Practical Example

While custom-coded strategies offer deep control, Vendure also provides a way to give non-developers control over business logic. For instance, what if a marketing manager needs to change the free shipping threshold for a weekend promotion without a code deployment?

This is where Configurable Operations are used. They are essentially strategies that can be configured through the Vendure Admin Dashboard at runtime, removing the need to restart the server for certain changes. A developer defines the core logic and exposes specific parameters, which an administrator can then modify.

Let's revisit our shipping calculator:

Instead of hard-coding rates and thresholds, we can build a ShippingCalculator that allows an administrator to set these values. This is still the Strategy Pattern at heart—the calculate method contains the algorithm—but now its behaviour is dynamically controlled by arguments set in the UI.

Here’s how you could define a flexible shipping calculator:

src/config/my-shipping-calculator.ts

You would then add this calculator to your main configuration file, making it available when creating new shipping methods in the Admin Dashboard.

src/vendure-config.ts

With this in place, an administrator can now create multiple shipping methods using this single piece of logic, each with different rates and free shipping thresholds, all without requiring a single line of new code. This is the ultimate expression of a flexible, composable architecture.

Conclusion

The Strategy Pattern is a cornerstone of flexible software design, and Vendure's architecture is a testament to its power. By providing a rich set of Strategies, Vendure allows developers to deeply customise core functionality. By layering Configurable Operations on top, it extends that flexibility to administrators, allowing them to adapt business logic on the fly.

Mastering these patterns is key to leveraging the full power of Vendure and building truly scalable, adaptable, and future-proof e-commerce solutions.

Further Reading

Share this article