Our previous blog post gave you an overview of the most popular eCommerce platforms based on Ruby, Node.js, and Python. We’ve evaluated them in terms of how quickly you can set up an online shop and what possibilities they give you. Turns out that Vendure.io, Spree, and Saleor are your best bets (choose according to your goals) — they are easy to implement, flexible, and provide room for customization.
Now, we’ll take a closer look to check what exactly you can do in terms of extending their out-of-the-box functionality, and how they perform under pressure.
Let’s dive in!
Vendure.io
Vendure.io is a quite new headless eCommerce platform that leverages Node.js, TypeScript, and GraphQL. The database is relational. Since so far this project has been mainly run by one guy — Michael Bromley — the platform packs only a few essential features.
Vendure.io is quick to set up and thanks to GraphQL it integrates with a frontend and additional features of your choosing really well.
To deploy Vendure on Heroku, you need to:
- Create a Heroku project.
- Add ROOT_URL.
- Add MySQL or Postgres as add-ons.
- Set an environment at Heroku.
- Add the heroku-nodejs package-builder.
- Deploy Vendure.io to Heroku.
Extensibility
As we’ve mentioned earlier, the platform itself is simple and basic, without any additional features. So if you need anything fancy, you’ll have to create it yourself. With that being said, Vendure.io is created with extensibility in mind. As the creator puts it, one of the main reasons to build the platform is:
I need to be able to faithfully model the business requirements and processes without bending to the dictates of the tools we use.
The plugins available right now are:
- AdminUiPlugin: Bundles a default build of the Vendure Admin UI and serves it when the server is started.
- AssetServerPlugin: Stores and serves assets from the local file system, and can perform on-the-fly image transformations.
- ElasticsearchPlugin: Allows your product search to be powered by Elasticsearch — a powerful Open Source search engine.
- EmailPlugin: Creates and sends transactional emails based on Vendure events.
To create custom plugins, you can refer to this document. The process is neatly described — it involves creating a new database entry and a GraphQL mutation.
Performance
Right now Vendure.io is best for simple and straightforward shops (those usually don’t face epic amounts of traffic), and for that purpose has a satisfying performance score. (We did all our tests on a free Heroku account so paid hosting will get you much better results.) For a single product, it can pull off 84.89 requests per second, with 33.07KB per second transfer. Here are the exact numbers:
====================
benchmark: query-comparison
--------------------
candidate: getproduct on getproduct at https://vendure-monte.herokuapp.com/
++++++++++++++++++++
400Req/s Duration:60s open connections:20
Running 1m test @ https://vendure-monte.herokuapp.com/
8 threads and 20 connections
Thread calibration: mean lat.: 4042.597ms, rate sampling interval: 13705ms
Thread calibration: mean lat.: 4094.949ms, rate sampling interval: 13828ms
Thread calibration: mean lat.: 4091.316ms, rate sampling interval: 13787ms
Thread calibration: mean lat.: 4118.664ms, rate sampling interval: 13975ms
Thread calibration: mean lat.: 4097.844ms, rate sampling interval: 13844ms
Thread calibration: mean lat.: 4126.541ms, rate sampling interval: 14090ms
Thread calibration: mean lat.: 4144.684ms, rate sampling interval: 14057ms
Thread calibration: mean lat.: 4125.240ms, rate sampling interval: 14008ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 26.24s 11.43s 47.42s 58.47%
Req/Sec 10.12 0.88 11.00 100.00%
5095 requests in 1.00m, 1.94MB read
Non-2xx or 3xx responses: 5095
Requests/sec: 84.89
Transfer/sec: 33.07KB
When it comes to requesting a full list of products, Vendure.io can handle 97.11 requests per second with 37.83KB per second transfer. Here are more details:
====================
benchmark: query-comparison
--------------------
candidate: getProducts on getProducts at https://vendure-monte.herokuapp.com/
++++++++++++++++++++
400Req/s Duration:60s open connections:20
Running 1m test @ https://vendure-monte.herokuapp.com/
8 threads and 20 connections
Thread calibration: mean lat.: 4112.211ms, rate sampling interval: 13819ms
Thread calibration: mean lat.: 4120.182ms, rate sampling interval: 13860ms
Thread calibration: mean lat.: 4150.881ms, rate sampling interval: 13852ms
Thread calibration: mean lat.: 4142.507ms, rate sampling interval: 14016ms
Thread calibration: mean lat.: 4166.577ms, rate sampling interval: 13910ms
Thread calibration: mean lat.: 4175.921ms, rate sampling interval: 14065ms
Thread calibration: mean lat.: 4193.582ms, rate sampling interval: 14065ms
Thread calibration: mean lat.: 4193.587ms, rate sampling interval: 14057ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 26.46s 10.76s 45.42s 58.22%
Req/Sec 12.00 0.00 12.00 100.00%
5828 requests in 1.00m, 2.22MB read
Non-2xx or 3xx responses: 5828
Requests/sec: 97.11
Transfer/sec: 37.83KB
Spree
Spree Commerce is an open-source eCommerce platform based on Ruby on Rails 6, REST API, and GraphQL. It also leverages relational databases. It has a large community and an established reputation.
As we’ve pointed out in our previous blog post, Spree would be best used for new shops (no product importer in Spree) that can make do with the UI shipped together with the platform. In theory, it’s possible to integrate Spree with another frontend, but in our experience, this process is not seamless and requires a time investment.
The setup, however, goes very smoothly. To install the platform, you need to:
rails new my_store
cd my_store
Next, in Rails 6.0 or in Rails 5.2:
gem 'spree', '~> 4.1'
gem 'spree_auth_devise', '~> 4.1'
gem 'spree_gateway', '~> 3.7'
Then:
bundle install
# in case of error
bundle update
rails g spree:install --user_class=Spree::User
rails g spree:auth:install
rails g spree_gateway:install
rails g spree:install --migrate=false --sample=false --seed=false --copy_storefront=false
rails s
Extensibility
Spree comes with a lot of advanced features out-of-the-box, with an impressive list of third-party integrations. This means that the majority of payment integrations are taken care of, and many marketing, mobile-first, and customer-facing features are already in place.
If you need something more than the core system provides, you can always check the list of existing extensions. Currently, there are:
- Support for Analytics Trackers
- Avalara AvaTax for tax decision automation
- Devise gem authentication services for Spree
- Paypal Express extension
- Contact Us form
- Extension enabling downloadable products
- Payment Gateways
And more.
In case your need is not covered by the available functionalities and extensions, you can always create your own plugin. You can start committing new functionalities to the local GitHub repository or create your own sandbox application.
Performance
In terms of performance, Spree packs the most punch out of the three platforms. For a single product request, it handles 456.67 requests per second with 210.05KB per second transfer.
wrk -t12 -c400 -d30s -H "X-Spree-Token: 6e332be3b4fffb003a88ee88c1c9036c8b041147c5e7a0e4" https://spree-e-commerce.herokuapp.com/api/v2/products/1
Running 30s test @ https://spree-e-commerce.herokuapp.com/api/v2/products/1
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 512.14ms 52.55ms 711.39ms 76.98%
Req/Sec 44.49 29.71 150.00 65.88%
13747 requests in 30.10s, 6.17MB read
Socket errors: connect 158, read 0, write 0, timeout 0
Requests/sec: 456.67
Transfer/sec: 210.05KB
When we’re fetching a list of all the products, Spree can handle 546.45 requests per second with 249.21KB per second transfer.
wrk -t12 -c400 -d30s -H "X-Spree-Token: 6e332be3b4fffb003a88ee88c1c9036c8b041147c5e7a0e4" https://spree-e-commerce.herokuapp.com/api/v2/products/
Running 30s test @ https://spree-e-commerce.herokuapp.com/api/v2/products/
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 428.17ms 31.38ms 514.23ms 88.02%
Req/Sec 51.48 30.98 171.00 61.30%
16448 requests in 30.10s, 7.33MB read
Socket errors: connect 158, read 0, write 0, timeout 0
Requests/sec: 546.45
Transfer/sec: 249.21KB
Saleor
Saleor is based on Python and Django, and the latest major update introduces a modular front end powered by a GraphQL API and written with React and TypeScript. It’s developed with flexibility in mind so adding new features is easy. It has a big and supportive community while being mature and well-developed at the same time. Saleor is basically a ready-made open-source product.
As we mentioned in our previous post, the localhost API and Heroku setup are lightning-fast (we managed to do it in two hours). Setting up the backend on Heroku is quite simple (just keep in mind that you’ll need to set additional environment variables if you’ll pin up the BE with the dashboard). There are instructions for deploying Saleor on different platforms. A Heroku environment variables setup might look like this:
ALLOWED_CLIENT_HOSTS=.ecommerce-saleor-dashboard.herokuapp.com
ALLOWED_HOSTS=.ecommerce-saleor-dashboard.herokuapp.com, .ecommerce-saleor.herokuapp.com
DEBUG=False (DEBUG=True by default)
To set up the dashboard, you’ll need to provide API_URI, e.g.:
API_URI=https://ecommerce-saleor.herokuapp.com/graphql/
You can also deploy Saleor locally, using this guide.
Extensibility
As we’ve mentioned, Saleor is basically a ready-made product. In most cases, there will be no need to develop additional features. However, to those who wish to extend the platform, Saleor also gives a helping hand.
Most importantly, the backend code is nicely structured and easy to navigate. All developers know this comes a long way when extending an app created by someone else. Additionally, the creators propose two ways of adding new features: through apps, and through plugins.
The documentation states that:
Apps are standalone web applications that are given access to Saleor's API. Apps can be given permissions and are able to perform most actions that a staff member is able to perform. Apps can also subscribe to certain events as they happen in Saleor and get notified about them using webhooks.
Plugins offer a way to run your code within the same application process as Saleor Core. Plugins are notified about events using callbacks and have direct access to the database.
Performance
Performance-wise, Saleor stands its ground. For a single product, it handles 92.07 requests per second with a 43.42KB per second transfer.
====================
benchmark: One product
--------------------
candidate: OneProduct on python-graphene at https://ecommerce-saleor.herokuapp.com/graphql/
++++++++++++++++++++
400Req/s Duration:60s open connections:20
Running 1m test @ https://ecommerce-saleor.herokuapp.com/graphql/
8 threads and 20 connections
Thread calibration: mean lat.: 5312.195ms, rate sampling interval: 15056ms
Thread calibration: mean lat.: 5316.608ms, rate sampling interval: 14991ms
Thread calibration: mean lat.: 5187.398ms, rate sampling interval: 14991ms
Thread calibration: mean lat.: 5200.366ms, rate sampling interval: 14942ms
Thread calibration: mean lat.: 5235.184ms, rate sampling interval: 14983ms
Thread calibration: mean lat.: 5153.267ms, rate sampling interval: 14794ms
Thread calibration: mean lat.: 5154.761ms, rate sampling interval: 14934ms
Thread calibration: mean lat.: 5249.303ms, rate sampling interval: 15040ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 27.40s 11.12s 46.37s 57.64%
Req/Sec 11.29 0.45 12.00 100.00%
5526 requests in 1.00m, 2.55MB read
Socket errors: connect 0, read 0, write 0, timeout 16
Non-2xx or 3xx responses: 5526
Requests/sec: 92.07
Transfer/sec: 43.42KB
For a list of products, Saleor handles 98.31 requests per second with a 64.99KB per second transfer.
====================
benchmark: All products
--------------------
candidate: AllProducts on python-graphene at https://ecommerce-saleor.herokuapp.com/graphql/
++++++++++++++++++++
400Req/s Duration:60s open connections:20
Running 1m test @ https://ecommerce-saleor.herokuapp.com/graphql/
8 threads and 20 connections
Thread calibration: mean lat.: 3983.652ms, rate sampling interval: 13484ms
Thread calibration: mean lat.: 4041.357ms, rate sampling interval: 13737ms
Thread calibration: mean lat.: 4137.041ms, rate sampling interval: 13852ms
Thread calibration: mean lat.: 4095.248ms, rate sampling interval: 13754ms
Thread calibration: mean lat.: 3972.554ms, rate sampling interval: 13467ms
Thread calibration: mean lat.: 4081.227ms, rate sampling interval: 13778ms
Thread calibration: mean lat.: 4024.856ms, rate sampling interval: 13524ms
Thread calibration: mean lat.: 4075.532ms, rate sampling interval: 13688ms
Thread Stats Avg Stdev Max +/- Stdev
Latency 26.23s 10.91s 45.45s 57.57%
Req/Sec 11.88 0.33 12.00 100.00%
5900 requests in 1.00m, 3.81MB read
Non-2xx or 3xx responses: 5900
Requests/sec: 98.31
Transfer/sec: 64.99KB
Since all the above tests were performed on a free Heroku account, they translate into superb performance on paid cloud hosting.
Summary
All three platforms are superstars in their own category.
Vendure.io will not choke up handling requests in any small or medium-sized shops. Although the out-of-the-box functionalities and existing plugins are rather basic, the process of creating new ones and implementing them in your shop is developer-friendly.
Spree is the Usain Bolt of our comparison. It handles requests so fast that they barely have the time to leave the user’s machine (quantum computing anyone?). Creating plugins here might be more cumbersome than on other platforms, but Spree has a lot to offer out of the box.
Saleor provides solid performance with a developer-friendly way of extending the core platform. It’s perfect for creating custom and user-friendly eCommerce platforms.
There you have it! If you want to be up-to-date with the posts in this series, simply sign up for our newsletter.
Also, here’s a list of all posts we’ve written on this topic so far: