---
title: "Focus On Behavior, Not State, for a More Maintainable Codebase"
description: "Shopify’s work adding pre-orders and “try before you buy” to its Purchase Options APIs exposed code that coupled selling plans too tightly to subscriptions, making future purchase models harder to add. The team reframed the domain around orders and behaviors, treating subscriptions as recurring orders and distinguishing recurring or deferred delivery and billing where those properties mattered. It introduced a wrapper around selling-plan Active Record objects, replaced those objects outside their defining component, and exposed methods such as whether deliveries are recurring while keeping policy details encapsulated. Because platform behavior and merchant reporting need different concepts, the team also added a translation table populated at order creation, with calculated or merchant-provided labels and optional trait records; the maintenance cost isolates reporting semantics from platform and data-team logic."
---

# Focus On Behavior, Not State, for a More Maintainable Codebase

[Shopify](https://yomu.fyi/company/shopify) · 2023-10-18 · Sep 1, 2022

**Type:** Explainer

## Summary

Shopify’s work adding pre-orders and “try before you buy” to its Purchase Options APIs exposed code that coupled selling plans too tightly to subscriptions, making future purchase models harder to add. The team reframed the domain around orders and behaviors, treating subscriptions as recurring orders and distinguishing recurring or deferred delivery and billing where those properties mattered. It introduced a wrapper around selling-plan Active Record objects, replaced those objects outside their defining component, and exposed methods such as whether deliveries are recurring while keeping policy details encapsulated. Because platform behavior and merchant reporting need different concepts, the team also added a translation table populated at order creation, with calculated or merchant-provided labels and optional trait records; the maintenance cost isolates reporting semantics from platform and data-team logic.

## Context

Adding pre-orders and try before you buy alongside subscriptions revealed that existing code often equated the presence of a selling plan with the subscription domain concept. That coupling made new purchase models such as installments or layaway harder to support and leaked selling-plan details into unrelated areas, including delivery, payments, and reporting.

## Approach / What changed

The team shifted from modeling state to exposing behavior. It treated a subscription as a recurring order, wrapped selling-plan Active Record objects in an object with higher-level methods, and replaced direct selling-plan usage outside its defining component. It also introduced a translation table for reporting, populated when an order is created with calculated, merchant-provided, or trait-based purchase labels.

## Takeaways

- A selling plan does not by itself establish subscription behavior: pre-orders may lack a delivery interval, while installments and layaway can involve recurring billing with different delivery patterns.
- Delivery and payments code can request the behavior it needs, such as recurring deliveries, delivery intervals, recurring payments, or deferred balances, without depending on the subscription concept.
- A reporting translation table can insulate data consumers from platform schema changes, while supporting calculated labels, merchant-provided labels, and stored traits at the cost of maintaining the translation layer.

**Tags:** [Architecture](https://yomu.fyi/topic/architecture), [Data Pipelines](https://yomu.fyi/topic/data-pipelines), [Refactoring](https://yomu.fyi/topic/refactoring)

- Source: [Shopify](https://shopify.engineering/behavior-not-state-for-maintainable-codebase)
- Source URL: https://shopify.engineering/behavior-not-state-for-maintainable-codebase
- Ingested by Yomu: 2026-08-30T13:39:18.530Z

[Read original post](https://shopify.engineering/behavior-not-state-for-maintainable-codebase)
