Migrating away from commercetools to a custom Solidus store

commercetools is genuinely strong enterprise software, and a true enterprise running many brands and regions from one commerce core is often right to stay. The shop I am writing for is the other one: the mid sized brand that was sold composable commerce, built a stack of services around the commercetools APIs, and now pays enterprise cost for a model heavier than the shop beneath it. In this article I explain, specifically for commercetools, how the HTTP and GraphQL APIs and the Import API really work, why there is no export button, and what the composable model locks in. You own your data, so leaving is a question of effort and fit rather than permission. For the deep detail on how each kind of data moves I link to the pieces that cover it rather than repeat them.

What commercetools is, and who outgrows it

commercetools is enterprise commerce software, and it is good at what it is for. It is API first and cloud native, run from Munich by commercetools GmbH, and it sells what the industry calls composable commerce: instead of one application that does everything, you get a set of commerce APIs (products, carts, orders, customers, payments) and you compose the rest of the shop around them.1 The company was a founding member of the MACH Alliance, the group that promotes architectures built from microservices, API first services, cloud native hosting and a headless frontend.2 If you run at real scale, with several brands, regions and sales channels drawing on one shared commerce core, and you have the team to run it, commercetools earns its place. This article is not for that business.

It is for the other one. The mid sized retailer or brand that was sold composable commerce, built a stack of separate services around the commercetools APIs, hired or rented the specialists to keep them talking to each other, and now looks at the annual cost against what the shop actually does and cannot make the sum work. For that business the honest question is not whether commercetools is good software. It is. The question is fit: do you need a composable platform and the team it implies, or would one owned application, that you can read end to end, serve the shop you actually run?

I build that owned application on Solidus, an open source commerce framework on Ruby on Rails under the permissive BSD 3 clause licence.3 I run the move and the client owns the result. This piece is specific to commercetools: how its APIs and its import and export really work, what the composable model locks in, and the honest shape of a move onto a single Rails shop. For the deep detail on how each kind of data travels I link to the articles that cover it rather than repeat them. Start with the overview of what moves and what does not.

Ownership is not the problem here. Fit and cost are

With a hosted shop like Shopify the honest wedge is often ownership: your data sits inside someone else's product and leaves on their terms. commercetools is not that. You own your data, it lives in a well documented model, and you can read it all back through the API. So I will not pretend the pitch is liberation. It is not.

The wedge is money and shape. Two things drive the move. The first is cost. commercetools does not publish a list price. Its pricing page sends you to sales and describes an order based model rather than a percentage of sales: in its own words, "unlike GMV based models, our order based approach ensures no hidden fees or penalties for scaling", with capabilities you mix and match and add ons such as Premium Support, an Audit Log, advanced B2B APIs, extra regions and a Checkout product.4 That is an enterprise contract, quoted to your volume, and for a mid sized shop it is frequently the largest single line in the technology budget. I will not invent a figure, because commercetools does not publish one and your quote is yours.

The second is shape. Composable commerce is not one bill. It is the commercetools licence plus the services you compose around it: a separate content system, a separate search and merchandising service, a frontend application somebody has to build and host, often a middleware layer that moves data between all of them, and the people who keep that mesh healthy. Each part can be excellent. Together they are a system that needs a standing team or a standing agency, and that cost does not fall when your order count does. A shop doing a few million a year can end up running the operating model of a shop doing a few hundred million. That is the mismatch the January budget review tends to find.

Getting your data out: the API, GraphQL, and why there is no export button

commercetools is an API first platform, so your data comes out the way everything else goes in: through the API. There are two surfaces over the same data.

The HTTP API is REST shaped and organised by Project, the top level container for all your data and configuration, addressed by a project key. The host follows the pattern https://api.{region}.commercetools.com, with the region fixed when you signed up, and every request carries an OAuth 2.0 bearer token.5 The GraphQL API sits at /{projectKey}/graphql as a single POST endpoint, reaches the same resources through the same clients and scopes, and lets you ask for exactly the fields and references you want in one query, which keeps an export script short.6

Here is the part that surprises people who assume an enterprise platform has an enterprise export tool. There is no symmetric bulk export API. commercetools gives you a rich asynchronous Import API for getting data in, and for getting data out it offers CSV export from the Merchant Center and a project sync command line tool for copying between Projects, but no single "export everything" endpoint.7 So a full extraction is a paging job against the Query API or GraphQL, resource by resource: products, product types, categories, customers, orders, carts, inventory, prices, custom objects.

The paging has a specific trap worth knowing before you start. A query returns at most 500 elements at a time, and offset based paging stops working past an offset of 10,000, so you cannot simply walk offset=0, 500, 1000 to the end of a large catalogue or customer base.8 You page with a predicate instead: sort by id and ask each time for the next block where the id is greater than the last one you saw. On top of that, Order Search only returns orders from the last three months, so the full order history has to come from the ordinary Orders query endpoint, not the search one.8 None of this is hard. It is a few hundred lines of careful script and a lot of checking. But it is work you plan for, not a button you press.

The data model, and why the mapping is the real job

The export is the easy half. The real work is the mapping, because commercetools models a catalogue more abstractly than a single shop application does.

A Product has a ProductType that defines its attributes, one or more Variants each with their own SKU, prices and attribute values, and localised fields for every language your Project supports. Prices can be embedded in a variant or kept as standalone prices, there are customer groups and channels, and almost every resource can carry a Custom Type with your own fields. The model is built to serve many frontends and many markets from one core, so it holds distinctions a single shop may never have used. Reference expansion is capped at three levels deep,8 which shapes how you pull related data in one pass.

Mapping that onto Solidus is a deliberate exercise, not a copy. Solidus has its own clean model: products, variants, option types and values, taxons, prices and stock. The questions that take the time are the ones only your team can answer. Which of the product attributes are still used and which are dead fields nobody has set in two years. Which localised strings matter for the markets you actually sell to. Which custom objects hold real logic and which were a workaround for something Solidus does natively. This is the same catalogue reconciliation I describe in migrating products and catalogue data, and it is where a migration is won or lost. Budget days of work here, with someone from the business beside you, not an afternoon.

Customers come across through the Customers API with their email, names, addresses, customer groups and custom fields. Passwords do not. commercetools manages a customer's password through its sign in, change password and reset endpoints and never hands the stored password back through the API, and it deletes the password outright if you switch that customer to external authentication.9 That is correct security and it is the same hard ceiling every platform has: you carry everything about the account except the secret, and customers set a new password on their first visit to the new shop. The accounts side is covered in full in migrating customer accounts and addresses.

The traps that are specific to commercetools

Every platform has its own way of holding on. commercetools does not lock your data, but the composable model has its own gravity.

The surrounding stack, not the core. The thing that is genuinely hard to leave is not commercetools the API. It is the web of services you built around it. The headless frontend, the content system, the search service, the integration layer: each has its own contract, its own data and its own quirks, and a move off commercetools usually means rethinking all of them at once, because they only ever existed to compose with the commerce core. On a single Solidus application most of that mesh collapses into one codebase. That is the point of the move, and also the reason it is a project rather than a weekend.

The specialist dependency. Composable commerce assumes a team that can hold several moving parts in its head. If that team is contractors or an agency, you are renting the knowledge of your own shop, and the day the engagement ends is the day the shop becomes hard to change. One owned Rails application, with its features covered by tests, is something a single competent developer can pick up and keep. That is a different operating model, and for a mid sized shop usually the right one.

Payments live at the gateway, as everywhere. commercetools models a Payment, but it says plainly that "the actual financial process is carried out by an external PSP", connected through a provider specific integration.10 So the saved cards and the recurring mandates are not inside commercetools to export. They sit with Stripe, Adyen, Mollie or whoever your provider is, as tokens that belong to that provider's account. If the new Solidus shop keeps the same provider and the same merchant account, the tokens stay valid and nothing needs re entering. If you change provider, a token migration is a certified process between the two providers, and it is the single hardest thing in any shop move. Settle it first, before a line of the new shop is built. The depth is in migrating payment tokens and saved cards, and the ways this goes wrong are in the hidden dangers of switching payment gateways.

SEO and URLs live in your frontend. Because commercetools is headless, your addresses, your redirects and your rendered pages were never commercetools' job. They live in the frontend you built, and they come with you only if you treat them as a first class deliverable. Every product, category and content URL that holds a ranking or a link needs a row in a redirect map and a permanent 301 to its new address, pointed straight at the destination and kept for at least a year. On the shops I build those redirects are a database table with an admin screen, so they survive every future deploy and your own staff can add one. The mechanics are in migrating products and catalogue data.

A worked example in Leeds

Let me make it concrete with an invented business. Moor and Larch (moorandlarch.example) is a Leeds homeware and outdoor living brand. It turns over about £5 million a year online across the UK and two European markets, with roughly 4,000 products and a healthy trade side selling to interior studios. Three years ago an agency moved it to a composable stack: commercetools for the commerce core, a headless content system, a hosted search and merchandising service, a Next.js storefront, and a middleware service wiring in the warehouse and the accounting system. It works. It is also carrying an operating model built for a far bigger company.

When the founder adds it up, the commercetools licence is the largest single technology line, quoted on order volume, and it sits on top of four other subscriptions and a standing agency retainer to keep the composition healthy. The shop does not need five brands and five regions. It needs a reliable UK and EU shop with a good trade price list. So the plan is to right size onto one owned Solidus application and keep the parts that genuinely pay their way.

The move settles the hard questions first. Moor and Larch already takes payment through its own Stripe account, so the new Solidus shop connects to that same account and the saved cards stay put: the worst problem in the project turns out not to apply, which is exactly why you check it on day one rather than week ten. Then the data. A paging script walks the Products, Customers and Orders endpoints with id predicates, because the catalogue and customer base are both well past the 10,000 offset ceiling, and because the full order history is older than the three months Order Search will return. Three years of orders come across as read only history, and the full export is archived for the accountant. The product mapping takes the longest: of the attributes defined on the commercetools product types, a good third turn out to be unused, and two custom objects that an agency built are features Solidus has natively.

The table the project runs on:

WhatHow it leaves commercetoolsWhere it lands
Products, variants, pricesQuery API or GraphQL, paged by id, then mappedSolidus products and variants (catalogue)
Customers, addressesCustomers API, no passwordsSolidus accounts, password reset on first visit (accounts)
Order historyOrders query endpoint, not Order SearchRead only order history (orders)
Saved cardsStay in the Stripe account, not in commercetoolsSame Stripe account, tokens unchanged (tokens)
URLs and SEOFrom the old frontend, not the commerce coreRedirect map, 301s in a Solidus admin table

By cutover, five services and one agency retainer have become one Rails application that the founder's own developer can read. The trade price list, the two European markets and the warehouse connection are features of the build, not subscriptions. What does not come down in price is honesty about the first year: the build is a real up front cost, which is the whole subject of the five year total cost of ownership.

The honest move onto Solidus

The shape of the project is the same one I run off any platform, with the commercetools specifics slotted in.

Discovery settles what is expensive to change later: the four column list of what migrates cleanly, partially, has to be rebuilt and cannot move, who in the business owns the data, and the payment decision, same provider or a token migration. The build runs the extraction scripts against a copy of the real Project again and again, so the final import on cutover day is boring. A parallel run of three to four weeks keeps the old stack live while the Solidus shop is tested on staging with real products and test payments, with the catalogue frozen so the two do not drift. Cutover happens on a quiet weekday morning: final import, counts checked against commercetools, domain pointed at the new shop, a real order placed and refunded for each payment method and country, the top URLs from the redirect map checked by hand. The old stack stays untouched for thirty days as the fallback, then the contracts are wound down.

Because commercetools is API first, one part is easier here than on a monolith: your organisation already thinks in terms of an API and a separate frontend, and Solidus can keep that shape. It has a full REST API, so if the mobile app or the custom frontend is a keeper, the new shop can serve it exactly as the old core did, which is the subject of headless and API first Solidus. You are not forced back into a monolith to escape the cost of composition. You are choosing a simpler one that you own.

When you should stay on commercetools

This matters as much as the rest, because for some readers the answer is to stay, and I would rather say so.

Stay if you genuinely run at the scale commercetools is built for: many brands or regions sharing one commerce core, high and spiky order volumes, a roadmap that needs microservices you can deploy and scale independently. Stay if you have the standing team, in house, that composable commerce assumes, and that team is busy and effective rather than a cost you resent. Stay if your constraint is throughput and global reach rather than the price of the licence. In those cases the platform is doing exactly what it was designed to do, and a single Rails application would be a step down, not a right sizing.

Move when the composable model is heavier than the shop beneath it: when you are paying enterprise cost and renting a specialist team to run an architecture whose scale you will not use, and what you actually need is a reliable, well tested shop you can own and change without three vendors in the room. The deciding question is not "is commercetools good". It is "do I need this operating model". The enterprise comparisons sit alongside this one: the same logic against Magento or Adobe Commerce and against SAP Commerce Cloud, and against the other open source headless option in migrating away from Medusa. If owning the data in a form a developer can read is the deeper worry, who actually owns your business data is the place to start.

What this means for you

commercetools is strong enterprise software, and leaving it is a question of effort and fit, never of permission, because the data is yours and the API hands it back. The effort is honest work: a paging extraction that respects the 500 element pages, the 10,000 offset ceiling and the three month order search window, a real mapping from an abstract composable model onto a single clean Solidus schema, passwords reset on first login, and payments settled before anything else. The reward is one owned Rails application in place of a rented composition, right sized to the shop you actually run.

If the commercetools bill and the stack around it have stopped matching the business beneath them, bring the licence quote, the subscriptions and the agency numbers to a free workshop, and the first two weeks of work are on me. I will put them against a Solidus build, flag the payment and mapping questions first, and tell you honestly whether moving pays off for you. Sometimes it does not, and I will say so.

Footnotes

  1. commercetools, About commercetools (headquartered in Munich as commercetools GmbH, cloud native and API first, the origin of headless commerce, and an enterprise commerce platform), accessed 14 November 2026, https://commercetools.com/company/about ↩

  2. MACH Alliance, commercetools member profile (founding member of the MACH Alliance and a composable commerce platform, where MACH stands for Microservices based, API first, Cloud native and Headless), accessed 14 November 2026, https://machalliance.org/members/commercetools ↩

  3. Solidus, solidusio/solidus repository on GitHub (an open source commerce framework on Ruby on Rails under the BSD 3 clause licence), accessed 14 November 2026, https://github.com/solidusio/solidus ↩

  4. commercetools, Pricing (no published list price, contact sales, an order based model described as unlike GMV based models, with packages and add ons including Premium Support, Audit Log, advanced B2B APIs, extra regions and Checkout), accessed 14 November 2026, https://commercetools.com/pricing ↩

  5. commercetools, API general concepts (HTTP API host pattern https://api.{region}.commercetools.com, OAuth 2.0 bearer tokens, isolated regions, and a Project as the top level container addressed by its project key), accessed 14 November 2026, https://docs.commercetools.com/api/general-concepts ↩

  6. commercetools, GraphQL API (a single POST endpoint at /{projectKey}/graphql over the same resources, clients and scopes as the HTTP API, with a query complexity limit of 20000), accessed 14 November 2026, https://docs.commercetools.com/api/graphql ↩

  7. commercetools, Import and Export overview (an asynchronous Import API using ImportContainers and ImportRequests of up to 20 resources each for products, prices, customers, orders, categories and more, with export offered as Merchant Center CSV and the commercetools project sync command line tool, but no single bulk export endpoint), accessed 14 November 2026, https://docs.commercetools.com/api/import-export/overview ↩

  8. commercetools, API limits (up to 500 elements per query, pagination maximum offset of 10000, expansion path depth of 3 references, 500 update actions per request, 14 MB request body, and Order Search returning orders from the last 3 months only), accessed 14 November 2026, https://docs.commercetools.com/api/limits ↩ ↩2 ↩3

  9. commercetools, Customers API (passwords handled through the sign in, change password and reset endpoints, never returned by the API, and deleted when a customer is switched to external authentication), accessed 14 November 2026, https://docs.commercetools.com/api/projects/customers ↩

  10. commercetools, Payments API (a Payment records the external provider, method, transactions and state, while "the actual financial process is carried out by an external PSP" connected through a provider specific integration), accessed 14 November 2026, https://docs.commercetools.com/api/projects/payments ↩

If the commercetools bill and the stack around it have stopped matching the business beneath them, bring the licence quote, the subscriptions and the agency numbers to a free workshop, and the first two weeks of work are on me. I will put them against a Solidus build, flag the payment and mapping questions first, and tell you honestly whether moving pays off for you. Sometimes it does not, and I will say so.

1%of every invoice goes to a UK charity you pick.

A donation, never sponsorship. You choose the cause at onboarding.

The story behind the pledge →

Stay ahead of your competition.

The latest innovative products and services, straight to your inbox before your competitors hear about them.

Get up to 5% off your first six months: 1% per topic you pick, the full 5% when you take everything. Limited offer · ends 31 December 2026.

New clients only. Terms apply.

* Up to 5% off your first six monthly invoices, new clients only. Full terms.

Questions about pricing, contracts or how we work together?

Read the FAQ