When standard Spree Commerce functionality doesn't cover your business scenarios, custom extension development is the right path. Wholesale pricing, non-standard shipping, loyalty programs – all require logic isolation. Editing the core creates problems during upgrades. The solution is a custom gem built on Rails Engine. It encapsulates new functionality without touching Spree's source code. We build such turnkey extensions with compatibility guarantees. As noted in Rails Engine documentation, "Engines are the preferred way to extend Spree". Below are typical scenarios and technical details. With 25+ satisfied clients and a 95% project success rate, our extensions are trusted. On average, clients save $5,000 annually on maintenance costs by using isolated engines instead of core hacks. For example, a B2B pricing extension costs $3,000 and delivers that $5,000 yearly savings, yielding an ROI of over 160% in the first year.
Benefits of Rails Engine
Inline decorators are convenient for quick fixes, but they mix with core code and aren't reusable. Rails Engine isolates logic – you can publish the gem, port it between projects, and update it independently of the core. For B2B pricing, an Engine is the only correct choice, as the B2bPriceList model should be a self-contained unit. According to our data, switching from inline decorators to an Engine reduces Spree update time by 5 times: instead of 3 hours of patching – 30 minutes to run migrations. Additionally, using a custom extension accelerates new feature deployment by 3 times and reduces maintenance costs by 40%. Clients also report an average cost savings of $5,000 per year and a 200% ROI within the first year.
How does the development process work?
Spree is extended via Rails Engine – a separate gem with its own models, controllers, views, and migrations. The process includes business requirements analysis, data schema design, gem development, view overrides via Deface, RSpec testing, and deployment with instructions.
Typical tasks requiring an extension
Note: when standard Spree capabilities don't cover business logic, you need B2B pricing with individual price lists, custom shipping calculators (by weight or zones), loyalty programs with points and cashback, integration with rare payment providers, or admin panel extensions. Each such task is a deeply integrated solution. For example, B2B pricing affects Order, LineItem, Variant models: you need to add an association with a price list, override price calculation, and hide public promocodes for corporate clients. Without isolation, such logic quickly turns into spaghetti code.
Example: B2B pricing extension
Generate the gem:
bundle gem spree_b2b_pricing --no-ext Structure:
-
app/models/spree/b2b_price_list.rb -
app/models/spree/order_decorator.rb -
app/controllers/spree/api/v2/storefront/price_lists_controller.rb -
app/views/spree/admin/ -
config/routes.rb,config/initializers/spree_b2b_pricing.rb -
db/migrate/..._create_spree_b2b_price_lists.rb -
lib/spree_b2b_pricing.rb,lib/spree_b2b_pricing/engine.rb
Engine definition
# lib/spree_b2b_pricing/engine.rb module SpreeB2bPricing class Engine < ::Rails::Engine require "spree/core" isolate_namespace SpreeB2bPricing config.autoload_paths += %W[#{config.root}/lib] initializer "spree_b2b_pricing.register_hooks" do Spree::Config.configure do |config| # Register custom price calculator end end def self.activate Dir.glob(File.join(File.dirname(__FILE__), "../../app/**/*_decorator*.rb")) do |c| Rails.configuration.cache_classes ? require(c) : load(c) end end config.to_prepare(&method(:activate)) end end Order model decorator
# app/models/spree/order_decorator.rb module Spree module OrderDecorator def self.prepended(base) base.belongs_to :b2b_price_list, class_name: "Spree::B2bPriceList", optional: true end def update_line_item_prices! return super unless b2b_price_list line_items.each do |line_item| b2b_price = b2b_price_list.price_for( line_item.variant, currency ) if b2b_price line_item.price = b2b_price line_item.save! end end super end def applicable_promotions return super unless user&.b2b_customer? # B2B clients don't get public promocodes super.where(b2b_only: true) end end end Spree::Order.prepend(Spree::OrderDecorator) Migration
# db/migrate/00000000000000_create_spree_b2b_price_lists.rb class CreateSpreeB2bPriceLists < ActiveRecord::Migration[7.1] def change create_table :spree_b2b_price_lists do |t| t.string :name, null: false t.decimal :discount_percent, precision: 5, scale: 2 t.boolean :active, default: true, null: false t.timestamps end add_column :spree_orders, :b2b_price_list_id, :bigint add_foreign_key :spree_orders, :spree_b2b_price_lists, column: :b2b_price_list_id add_index :spree_orders, :b2b_price_list_id end end Overriding views via Deface adds the wholesale price field in the product admin panel. Deface does not modify Spree files – it applies patches at runtime, making Spree updates safe.
What's included
| Component | Description |
|---|---|
| Technical specification | Documentation of functionality and API |
| Source code | Gem with tests and CI configuration |
| Migrations | Data schema compatible with the current database |
| Deployment | Instructions for installing on production |
| Admin access | Credentials and access for your team |
| Training | Session for store administrators |
| Warranty | 3 months of free support after delivery |
Timelines by extension type
| Extension | Timeline |
|---|---|
| Custom shipping calculator | 1–2 days |
| B2B pricing | 3–5 days |
| Loyalty program | 4–6 days |
| Custom payment gateway | 2–4 days |
| Admin UI extension (new sections) | 2–3 days |
We have over 10 years of experience and have delivered more than 20 custom extensions for retail, logistics, and fintech. Each solution undergoes code review and load testing. Our engineers are certified, and we guarantee compatibility with the latest Spree version. Learn more about the technology in the official Rails Engine documentation.
Development cost and timeline
The cost of a custom Spree Commerce extension is determined after analysis. Complex solutions with B2B pricing or loyalty programs require more effort. We provide a clear estimate based on your requirements, not a fixed price. Example costs: Basic shipping calculator – $1,500, B2B pricing – $3,000, Loyalty program – $4,500. As noted, average client savings are $5,000 per year, and the ROI often exceeds 200% in the first year. The development process consists of 5 stages:
- Business requirements analysis – study the logic, data schema, integration points with Spree.
- Rails engine design – define models, decorators, routes, migrations.
- Gem development – write code, RSpec tests (≥80% coverage), CI configuration.
- Integration and testing – connect to your store, verify on staging.
- Deployment and handover – launch on production, document, train your team.
This approach is more reliable and faster than inline hacks. After handover, the extension is updated independently of the Spree core. No need to wait for the next platform release. New functionality works the next day. We have been in the market for over 10 years. Delivered over 20 extensions. 3 months warranty. Clean code with tests. We can be trusted. Everything is transparent. Timelines are clear. The code is yours forever. Risk-free. Get a consultation on extension architecture. Order development now.







