Loading…
Componentizing Shopify’s Tax Engine
2023-10-18
- Source
- Shopify
- Published
- Added to Yomu
Summary
Shopify’s tax engine grew from a simple system into difficult code as tax rules and ownership spread across Cart, Checkout, and Order. The team first learned the surrounding code and tax domain with help from a tax subject matter expert, then mapped dependencies using regular expressions, scripts, manual investigation, and tax-related bug work. They moved tax source files into a dedicated component behind explicit TaxesRequestSchema and TaxesReponseSchema interfaces, with simple-type request and response schemas, protected boundaries, and expanded unit, integration, and end-to-end tests. During release, the old and new engines calculated taxes concurrently so discrepancies could be measured; after iterative fixes, Shopify rolled the component out gradually from a small group of shops to all shops over several days, with no downtime or merchant impact reported.
Context
Tax calculations depend on factors including product type, customer location, shipping origin, and physical and economic nexus. Over time, tax logic became intertwined with multiple systems, whose separate uses of the engine could create inconsistent behavior and make changes difficult.
Approach / What changed
The team defined a dedicated tax component with explicit request and response schemas, moved tax-related source files behind its boundary, added monitoring for new dependencies, expanded testing, and compared old and new calculations during a gradual production rollout.
Takeaways
- The tax interface used TaxesRequestSchema and TaxesReponseSchema, composed of simple types so callers and tax logic did not depend on each other’s implementation details.
- GitHub bot triggers notified the team about commits affecting tax component files, helping prevent new dependencies from bypassing the component boundary during the migration.
- The new and old engines ran concurrently during experimentation, with new-component results discarded until discrepancies were resolved; production adoption then expanded from a small group of shops to 100% over several days.