Drupal Commerce: How to Build Online Store from Modular Components on Your Own VPS

19.03.2026
17:39

Building trading platform can follow two paths — take ready template and configure it or assemble solution from independent blocks for specific task. Drupal Commerce belongs to second type. This is not out-of-box store like PrestaShop but toolkit for constructing own sales architecture.

Platform appeared in 2011 as result of complete Übercart module rework. Today serves trade turnover over billion dollars annually on platforms like British Royal Mail (UK postal service with millions of transactions), international Eurocentres language school network, McDonald's France. Works on 42,000+ active sites worldwide.

This material covers platform's technical side — from modular architecture philosophy to practical VPS installation with PostgreSQL. Shows where Drupal Commerce wins against WooCommerce and Magento and where it loses. Gives hosting recommendations in 50+ THE.Hosting locations for different geographic markets.

Architectural Philosophy: Framework Against Application

Most e-commerce platforms designed as finished applications. Install Shopify, get working store with cart, checkout, admin panel. Customization goes through settings and plugins on top of base functionality.

Drupal Commerce follows opposite approach — framework-first mindset. Instead of ready store gives building blocks: product type system, product variation mechanism, pricing rules, order processor. From these components assemble needed configuration.

Practical difference example:

WooCommerce says: "Here's ready store, add products and launch". Drupal Commerce answers: "Define product types for your business, configure attributes, assemble purchase process from steps, connect needed payment methods".

First approach faster at start. Second more flexible when scaling and non-standard requirements.

Modular structure in practice:

Commerce Core — base kernel with data entities. Product, order, customer cart, payment method, shipping profile — all separate data types living independently. Can use products without cart (catalog), cart without checkout (wishlist), payments without products (donations).

Commerce Product — product management. Creating product types with unique fields, variation system (one product in different sizes/colors), categorization through Drupal taxonomy.

Commerce Cart — shopping cart functionality. Adding items, quantity changes, applying promo codes, saving between sessions.

Commerce Checkout — order processing. Assembly from steps: customer info, shipping address, shipping method selection, payment, order review, confirmation. Each step optional and configurable.

Commerce Payment — payment system integration. Unified API for connecting gateways, card tokenization, delayed charges, refunds.

Modularity advantages:

Start with minimal set — only what actually needed. Digital store without physical shipping doesn't drag stock management and dimensions calculation modules. Donation site uses payment system without product catalog.

Add features as you grow. Started with simple products — added variations when assortment expanded. Subscriptions appeared — installed Commerce Recurring. Went international — added multicurrency.

Replace components without rewriting everything. Standard checkout process didn't fit — write your own, rest works as before. Changed payment gateway — change only payment module.

Integration with Drupal CMS: Content Plus Commerce

Drupal Commerce built on top of Drupal — enterprise-level content management system. This gives advantages pure e-commerce solutions don't have.

Single platform for content and sales:

Product in Drupal Commerce is content type alongside articles, pages, media files. Apply same tools as for regular content — access permissions, publishing workflow, versioning, scheduling, translations.

Create rich product pages through Layout Builder — visual block editor. Place description, technical specifications, video reviews, customer reviews, related products, usage articles — all on one page without programming.

Drupal category system works simply — create sections within sections to any depth. Example: Clothing → Outerwear → Jackets → Winter Jackets. Add tags so one product appears in different places. Filters by parameters (price, brand, size) build automatically. Same logic works for blog articles, help pages, news — don't need to learn different systems.

Built-in content marketing:

Write articles about product usage — automatically link to products. Publish video instructions — embed product blocks right in material. Run blog — highlight product mentions with purchase links.

Data presentation module builds any content and product lists by flexible rules. "Products from category X with price Y-Z, bought by customers who viewed article A" — such selections assembled through interface without SQL.

Drupal SEO tools work for products automatically. Pathauto generates clean URLs, Metatag manages meta tags, Schema.org markup adds structured data for search engines. XML sitemap includes product pages alongside content.

Multilingual without hacks:

Drupal supports 100+ languages including right-to-left writing (Arabic, Hebrew). Translate products, categories, store interface — all through single localization system. One site serves worldwide customers, language auto-detection by IP or manual selection.

Content and commerce translate identically. Product description, specifications, reviews — same translation work as blog articles. No need for separate catalog and content tools.

Access permissions and roles:

Permission separation works at content types, fields, operations level. Catalog manager sees and edits products but can't touch orders. Accountant accesses payments and refunds without price changing rights. Content manager publishes articles but doesn't touch store settings.

Create roles for company organizational structure. Salesperson, warehouse worker, marketer, analyst — each gets own operation permissions set on data.

Technical Stack and System Requirements

Drupal Commerce works on standard LAMP/LEMP stack with PHP 8.1+ and modern database.

Mandatory components:

PHP 8.1 minimum, recommended 8.2-8.3. Newer versions give 20-30% performance gain versus 7.4. Need extensions: mbstring, xml, gd, curl, zip, opcache, intl, bcmath, pgsql/mysqli.

Drupal 10.3+ or Drupal 11. Versions 9 and below don't support Commerce Core 3.x. Upgrade from Drupal 9 to 10-11 passes relatively painless if not using deprecated APIs.

Database: PostgreSQL 12+, MySQL 5.7.8+ or MariaDB 10.3+. PostgreSQL preferable for complex queries — full-text search works faster, JSON fields process more efficiently, transactions more reliable.

Composer 2.0+ for dependency management. Drupal long ago abandoned manual module installation through admin panel, everything through Composer. Drush — command console for administrative operations (cache clearing, running migrations, updating DB schemas).

Recommended server configuration:

Minimum for production: 4 vCPU, 8 GB RAM, 80 GB NVMe SSD. This covers PHP-FPM with 8-10 workers (500 MB each), PostgreSQL with 2-3 GB buffers, Redis 1 GB for cache, OS and background process reserve.

For catalog over 10,000 items and traffic 500+ simultaneous visitors need 8 vCPU, 16 GB RAM. At 50,000+ products consider dedicated servers with 16-32 GB RAM and NVMe RAID for database.

Why NVMe is critical:

PostgreSQL actively works with disk — indexes, temporary tables for complex queries, WAL transaction logs. On SATA store with 10,000 products lags at 30-40 simultaneous users. NVMe gives 5-10x random read/write speed boost directly affecting page responsiveness.

Tests show: product page generation with variations, prices, related products on SATA takes 800-1200ms. On NVMe same operation fits 150-200ms. Difference noticeable for users.

Additional services:

Redis mandatory for caching. Drupal generates lots of intermediate data — rendered blocks, query results, compiled templates. Redis keeps this in memory, 3-5x acceleration versus file cache.

Varnish or other HTTP cache optional but desirable for high loads. Caches entire pages at web server level, delivery without PHP access. For anonymous traffic reduces load by multiples.

Elasticsearch or Solr for full-text search if catalog bigger than 5,000 products. Database search slow on volumes, search engines give subsecond results even on millions of records.

THE.Hosting location choice:

For European audience optimal Netherlands (Meppel) — central point with excellent connectivity, or Germany (Frankfurt) — financial capital with premium infrastructure. Latency for Western Europe 10-20ms, for Eastern 30-50ms.

Asian customers require local placement. Japan (Tokyo) optimal for East Asia including Korea, Taiwan, Philippines with 10-30ms latency. Hong Kong covers China and Southeast Asia. South Korea (Seoul) provides access to region's high-speed infrastructure.

CIS market served from Poland (Warsaw) or Romania (Bucharest). Moldova (Chișinău) offers Dedicated servers for large projects. American market — USA (New Jersey) for East Coast.

THE.Hosting provides NVMe disks on all plans including budget, root access for environment setup, 24/7 support. Can raise multiple VPS in different locations for testing performance for specific audience.

Installation and Initial Configuration

Drupal Commerce deployment consists of several stages: installing base Drupal system, adding Commerce modules, configuring product types and payments.

Environment preparation on Ubuntu 24.04:

Update system and install dependencies:

sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl wget unzip software-properties-common

PHP 8.3 from Ondřej Surý repository:

sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
sudo apt install -y php8.3-fpm php8.3-cli php8.3-pgsql php8.3-gd \
  php8.3-curl php8.3-mbstring php8.3-xml php8.3-zip php8.3-intl \
  php8.3-bcmath php8.3-opcache php8.3-redis

Latest Composer:

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

PostgreSQL 16:

sudo apt install -y postgresql postgresql-contrib
sudo systemctl enable postgresql

Database and user creation:

sudo -u postgres psql
CREATE DATABASE drupal_shop WITH ENCODING 'UTF8' LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' TEMPLATE=template0;
CREATE USER shop_user WITH PASSWORD 'secure_password';
GRANT ALL PRIVILEGES ON DATABASE drupal_shop TO shop_user;
ALTER DATABASE drupal_shop OWNER TO shop_user;
\q

Drupal installation via Composer:

cd /var/www
sudo composer create-project drupal/recommended-project shop
cd shop

Adding Commerce modules:

composer require drupal/commerce

Web server access permissions:

sudo chown -R www-dаta:www-data /var/www/shop
sudo chmod -R 755 /var/www/shop
sudo chmod -R 775 web/sites/default/files

Drush for command work:

composer require drush/drush
echo 'export PATH="$PATH:/var/www/shop/vendor/bin"' >> ~/.bashrc
source ~/.bashrc

Drupal installation:

drush site:install standard \
  --db-url=pgsql://shop_user:secure_password@localhost/drupal_shop \
  --site-name="Online Store" \
  --account-name=admin \
  --account-pass=strong_admin_password \
  -y

Commerce activation:

drush pm:enable commerce commerce_product commerce_order \
  commerce_cart commerce_checkout commerce_payment -y

Nginx configuration:

Create file /etc/nginx/sites-available/shop:

server {
    listen 80;
    server_name shop.example.com;
    root /var/www/shop/web;
    index index.php;

    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt { log_not_found off; access_log off; }

    location ~ \..*/.*\.php$ { return 403; }
    location ~ ^/sites/.*/private/ { return 403; }
    location ~ ^/sites/[^/]+/files/.*\.php$ { deny all; }

    location / {
        try_files $uri /index.php?$query_string;
    }

    location @rewrite {
        rewrite ^ /index.php;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

Activation and restart:

sudo ln -s /etc/nginx/sites-available/shop /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

SSL certificate:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d shop.example.com

Redis for caching:

Installation:

sudo apt install -y redis-server
sudo systemctl enable redis-server

Redis module for Drupal:

composer require drupal/redis
drush pm:enable redis -y

Configuration in web/sites/default/settings.php:

$settings['redis.connection']['interface'] = 'PhpRedis';
$settings['redis.connection']['host'] = '127.0.0.1';
$settings['redis.connection']['port'] = 6379;
$settings['cache']['default'] = 'cache.backend.redis';
$settings['cache']['bins']['bootstrap'] = 'cache.backend.chainedfast';
$settings['cache']['bins']['discovery'] = 'cache.backend.chainedfast';
$settings['cache']['bins']['config'] = 'cache.backend.chainedfast';

Installation verification:

Open https://shop.example.com/admin — Drupal admin should load. In "Extensions" section verify Commerce modules enabled and working.

Catalog Configuration

After base installation configure catalog structure for specific business.

Creating product type:

Go to Commerce → Configuration → Product types → Add product type. For example, for clothing store create "Clothing" type with fields:

  • Material (list: cotton, polyester, wool)
  • Season (list: summer, winter, all-season)
  • Gender (list: men's, women's, unisex)
  • Care instructions (long text)

For electronics "Gadgets" type:

  • Manufacturer (taxonomy brand link)
  • Warranty (months number)
  • Technical specifications (parameters table)
  • Package contents (items list)

Attributes for variations:

Attributes define by which parameters product has variations. For clothing usually size and color. Create "Size" attribute with values S, M, L, XL, XXL. "Color" attribute — black, white, red, blue.

When adding product, system generates all attribute combinations as separate variations. T-shirt in 5 sizes and 4 colors gives 20 variations, each with unique price and stock quantity.

Taxonomy for categories:

Structure → Taxonomy → Add vocabulary "Product Categories". Create hierarchy:

  • Clothing
    • Outerwear
      • Jackets
      • Coats
    • T-shirts
    • Pants
  • Footwear
    • Sneakers
    • Boots

Products bind to categories through taxonomy field. One product can be in multiple categories for cross-navigation.

Price setup:

By default each product variation has one price. For complex pricing use Commerce Price List module:

composer require drupal/commerce_pricelist
drush pm:enable commerce_pricelist -y

Create price lists for different conditions:

  • Wholesale price (from 10 pieces)
  • Corporate price (for legal entities)
  • Promotional price (temporary discounts)

Price lists apply by rules: user role, cart quantity, purchase date.

Payment Systems and Order Processing

Connecting payment methods — critical store setup stage.

Stripe integration:

Install module:

composer require drupal/commerce_stripe
drush pm:enable commerce_stripe -y

Commerce → Configuration → Payment methods → Add payment method → Stripe. Specify:

  • Publishable key (public key from Stripe Dashboard)
  • Secret key
  • Operating mode (test/live)

Stripe supports card tokenization — card number never hits your server, processed on Stripe side through jаvascript widget. PCI DSS compliance automatic.

PayPal Express Checkout:

composer require drupal/commerce_paypal
drush pm:enable commerce_paypal -y

Add PayPal payment method, enter API credentials. PayPal allows payment without site registration — customer goes to PayPal, authorizes there, returns with confirmed payment.

Local processors:

For Russian market popular ЮKassa, Tinkoff Kassa, Sberbank. Look for contributed modules on drupal.org or write integration yourself through Commerce Payment API.

Order workflow:

Order passes through states: Draft → Placed → Processing → Completed → Canceled. Each transition can trigger actions: send email, update stocks, warehouse notification.

Configure transitions through Rules module:

  • On transition to "Placed" → send customer confirmation email
  • On transition to "Completed" → decrease product stock quantities
  • On cancellation → return products to available

Shipping and Inventory

Physical products require shipping cost calculation and stock management.

Commerce Shipping:

composer require drupal/commerce_shipping
drush pm:enable commerce_shipping -y

Create shipping methods:

  • Courier delivery (fixed city cost)
  • Russian Post (calculation by weight and zone)
  • Pickup points (free from order amount)

For each method configure application conditions and calculation rules. Can integrate delivery service APIs for getting real rates.

Commerce Stock for inventory:

composer require drupal/commerce_stock
drush pm:enable commerce_stock -y

Enable stock tracking for product types. When adding to cart system checks availability, at checkout — reserves quantity, at payment — writes off finally.

For multiple warehouses create locations and distribute stocks between them. Order automatically assembled from nearest warehouse to shipping address.

Promotion and Marketing

Drupal Commerce provides tools for stimulating sales.

Commerce Promotion for campaigns:

composer require drupal/commerce_promotion
drush pm:enable commerce_promotion -y

Promotion types:

  • Percentage cart discount (10% of total)
  • Fixed discount (500 rubles at order from 5000)
  • Code coupons (customer enters at checkout)
  • Free shipping from amount
  • Gift product when buying set

Application conditions: product category, user role, validity period, coupon usage count.

Email marketing:

Integration with Mailchimp or SendGrid for automatic mailings:

  • Welcome email after registration
  • Abandoned cart (reminder after 24 hours)
  • Recommendations based on viewed
  • New arrivals information

SEO optimization:

Pathauto, Metatag, Schema.org Metatag modules automate SEO:

composer require drupal/pathauto drupal/metatag drupal/schema_metatag
drush pm:enable pathauto metatag schema_metatag -y

Pathauto generates clean URLs like /clothing/tshirts/nike-sport-tshirt. Metatag manages meta tags for each product page. Schema.org adds Product micromarkup for rich snippets in search.

Performance on High Loads

Store with thousands daily visitors requires optimization.

Varnish HTTP cache:

Installing Varnish before Nginx caches ready HTML pages. Anonymous users get content directly from Varnish without PHP access.

VCL file configuration for excluding personalized pages (cart, account) from cache, invalidation on product changes through Purge module.

CDN for media files:

Product images, CSS, jаvascript served through CloudFlare or other CDN. Reduces server load, speeds loading for users from different regions.

Drupal CDN module automatically rewrites static file URLs to CDN domain.

Database query optimization:

PostgreSQL configuration for e-commerce load in /etc/postgresql/16/main/postgresql.conf:

shared_buffers = 4GB
effective_cache_size = 12GB
maintenance_work_mem = 1GB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
random_page_cost = 1.1
effective_io_concurrency = 200
work_mem = 32MB
max_worker_processes = 4
max_parallel_workers_per_gather = 2
max_parallel_workers = 4

Regular maintenance:

sudo -u postgres vacuumdb --analyze --verbose drupal_shop

Performance monitoring:

New Relic or Blackfire.io for profiling slow queries and pages. Identifying bottlenecks in code, optimizing problem areas.

Competitor Comparison

Drupal Commerce vs WooCommerce:

WooCommerce simpler at entry — WordPress familiar to many, plugin installation takes minutes. Drupal Commerce requires Drupal understanding raising entry barrier.

WooCommerce has thousands of paid extensions for any function. Drupal Commerce ecosystem smaller — 300 modules versus several thousand, specific integrations written custom.

Drupal Commerce excels in data flexibility. Product types with arbitrary fields, complex variations, entity relationships — customization level higher. WooCommerce tied to WordPress post structure.

For content-rich projects (blog + store, learning platform + course sales) Drupal Commerce gives unified system. WooCommerce is plugin to blog platform.

Drupal Commerce vs Magento:

Magento heavyweight — requires serious server resources even for medium store. Drupal Commerce lighter, works on modest hardware.

Magento sharpened exclusively for commerce. Drupal Commerce more universal thanks to CMS foundation — equally good for store, portal, community.

Magento has ready functionality for B2B (corporate prices, quote requests, credit limits). In Drupal Commerce this assembled from modules or written custom.

Both scale to enterprise level. Magento more popular in large retail, Drupal Commerce more common in projects where content matters as much as sales.

Drupal Commerce vs Shopify:

Shopify SaaS platform — no hosting, infrastructure, updates. Pay fixed monthly sum, everything works. Drupal Commerce requires own hosting and administration.

Shopify takes sales percentage (0.5-2% depending on plan). Drupal Commerce has no commissions — only your hosting and development costs.

Shopify limited by platform functionality. Customization possible but within Shopify API. Drupal Commerce gives full code and data control.

For quick start with minimal investment Shopify better. For projects with non-standard requirements and long-term perspective Drupal Commerce wins.

Real Use Cases

Royal Mail (United Kingdom):

National postal service uses Drupal Commerce for selling stamps, envelopes, packaging materials online. Millions transactions annually, integration with warehouse and logistics systems.

Technical solution: cluster of several application servers, PostgreSQL in master-standby configuration, Varnish for HTTP cache, Elasticsearch for catalog search.

Eurocentres (international network):

Language school network in 30+ countries sells English, German, French courses through single Drupal Commerce site. Multilingual, multicurrency, localized content for each region.

One Drupal installation serves all countries, language and currency auto-detection by IP. School content translated to 15 languages, prices in local currencies with auto-conversion.

McDonald's France:

Franchise network uses Drupal Commerce for selling franchises, training materials, branded products to franchisees. Closed system with access only for current partners.

Implementation through private content with strict permission system. Different franchisee levels see different catalogs and prices according to contract terms.

Conclusion

Drupal Commerce occupies niche between ready solutions (WooCommerce, Shopify) and enterprise platforms (Magento, SAP Commerce). Suits teams with PHP expertise needing architecture flexibility but lacking heavyweight systems budget.

Modular structure allows starting with minimal feature set and expanding as growing. Drupal CMS integration gives advantages for content-oriented projects. Open-source without vendor lock-in guarantees independence and data control.

Developer requirements higher than simple platforms. Need understanding of Symfony components, Drupal architectural patterns, experience with Composer and Drush. Consultants cost $80-150/hour making project more expensive than hosted solutions at start but pays off at scale.

THE.Hosting in 50+ locations gives placement flexibility for audience geography. Netherlands and Germany for Europe, Japan and Hong Kong for Asia, USA for American market. NVMe disks, root access, 24/7 support — everything necessary for production deployment.

Useful Links

Drupal Commerce:

THE.Hosting:

Other articles