# SAP Commerce Cloud Architecture Overview

> SAP Commerce Cloud architecture: platform services, CCv2 aspects, deployment pipelines, cluster topology, and integration patterns.

Source: https://www.commercecloudintegrations.com/guides/sap-commerce-cloud-architecture-overview
Publisher: Commerce Cloud Integrations
Updated: 2026-08-11
Topics: architecture, ccv2, deployment, platform, cloud

SAP Commerce Cloud (formerly Hybris) is a Java-based e-commerce platform built on Spring Framework, deployed on a managed cloud infrastructure (CCv2). This guide covers the core architectural patterns that every commerce architect and developer must understand: platform services, the extension system, CCv2-specific deployment model, and integration patterns.

## Platform Services Architecture

The SAP Commerce platform is built around a service-oriented architecture with three key layers:

1. **Type System**: dynamic data model with runtime type definition
2. **Service Layer**: business logic, transactions, validation
3. **Facades**: simplified API for frontend/integration consumption

### Type System

SAP Commerce uses a custom type system defined in `*-items.xml` files. Types are compiled into JaLo classes (legacy) and Models (current standard).

```xml
<itemtype code="Product" extends="GenericItem">
  <deployment table="products" typecode="1"/>
  <attributes>
    <attribute qualifier="code" type="java.lang.String">
      <modifiers unique="true" optional="false"/>
      <persistence type="property"/>
    </attribute>
    <attribute qualifier="name" type="localized:java.lang.String">
      <persistence type="property"/>
    </attribute>
    <attribute qualifier="catalogVersion" type="CatalogVersion">
      <modifiers optional="false"/>
      <persistence type="property"/>
    </attribute>
  </attributes>
</itemtype>
```

Key type system concepts:

- **Deployment**: table name + typecode (numeric identifier for serialization)
- **Attributes**: can be stored (persisted to DB) or dynamic (calculated at runtime)
- **Relations**: one-to-many and many-to-many via separate relation items
- **Interceptors**: validate, prepare, or react to model changes (lifecycle hooks)
- **Localization**: attributes can be localized per language via `localized:` prefix

### Service Layer

Business logic lives in service beans. Services are Spring-managed, transactional, and testable:

```java
@Service
public class DefaultProductService implements ProductService {

  @Resource
  private FlexibleSearchService flexibleSearchService;

  @Resource
  private ModelService modelService;

  @Override
  public ProductModel getProductForCode(String code) {
    final FlexibleSearchQuery query = new FlexibleSearchQuery(
      "SELECT {pk} FROM {Product} WHERE {code} = ?code"
    );
    query.addQueryParameter("code", code);
    return flexibleSearchService.searchUnique(query);
  }

  @Override
  @Transactional
  public void updateProduct(ProductModel product) {
    modelService.save(product);
  }
}
```

Service layer best practices:

- Use **FlexibleSearch** for queries (platform-managed SQL abstraction)
- Transaction boundaries via `@Transactional` (Spring TX)
- Validation via **Interceptors** and **Validators**
- No UI concerns. Service layer is backend-only
- Avoid direct DAO access. Use ModelService for CRUD

### Facades

Facades simplify service layer complexity for frontends and integrations. They convert Models to DTOs (Data Transfer Objects):

```java
@Component
public class DefaultProductFacade implements ProductFacade {

  @Resource
  private ProductService productService;

  @Resource
  private Converter<ProductModel, ProductData> productConverter;

  @Override
  public ProductData getProductForCode(String code) {
    final ProductModel product = productService.getProductForCode(code);
    return productConverter.convert(product);
  }
}
```

Facades return **DTOs** (Data Transfer Objects), never models directly. DTOs are serialization-safe, versioned, and decouple the API from internal models.

## Extension System

SAP Commerce is modular. All functionality ships as **extensions**. Core platform extensions:

| Extension                      | Purpose                                      |
| ------------------------------ | -------------------------------------------- |
| `core`                         | Platform kernel, type system, Spring context |
| `catalog`                      | Catalogs, categories, classification         |
| `basecommerce`                 | Product, price, stock fundamentals           |
| `commercefacades`              | Standard facades + DTOs                      |
| `commerceservices`             | Standard services (cart, order, customer)    |
| `commercewebservices`          | OCC REST API (headless commerce)             |
| `backoffice`                   | Admin UI framework                           |
| `acceleratorservices`          | B2C/B2B storefront foundation                |
| `acceleratorstorefrontcommons` | Storefront web layer (controllers, tags)     |

### Extension Structure

```
myextension/
├── extensioninfo.xml          # extension metadata, dependencies
├── project.properties          # build config, cache regions
├── resources/
│   ├── myextension-items.xml  # type system definitions
│   ├── myextension-spring.xml # Spring bean wiring
│   ├── localization/          # i18n bundles
│   └── impex/                 # initial data, migrations
├── src/                        # Java source
├── testsrc/                    # unit/integration tests
└── web/                        # web UI (storefront/backoffice)
```

Extensions declare dependencies in `extensioninfo.xml`:

```xml
<extension name="myextension">
  <requires-extension name="commerceservices"/>
  <requires-extension name="commercefacades"/>
  <coremodule generated="true" packageroot="com.example.myextension"/>
  <webmodule webroot="/myextension"/>
</extension>
```

Build order is calculated from dependency graph. Circular dependencies are rejected at compile time.

## CCv2 Architecture (SAP Commerce Cloud v2)

CCv2 is the managed cloud platform for SAP Commerce. It introduces **aspects**, independently scalable deployment units.

### Aspect Model

An aspect is a logical deployment unit with a specific role. CCv2 supports:

| Aspect                 | Purpose                                 | Scalability                |
| ---------------------- | --------------------------------------- | -------------------------- |
| `accstorefront`        | Customer-facing storefront (B2C/B2B)    | Horizontal (auto-scale)    |
| `backoffice`           | Admin UI for content/catalog management | Vertical (fixed instances) |
| `backgroundProcessing` | Async jobs (cronjobs, indexing, batch)  | Horizontal (job-based)     |
| `api`                  | OCC REST API (headless commerce)        | Horizontal (auto-scale)    |
| `admin`                | Platform admin and initialisation tasks | Vertical (fixed)           |

Each aspect runs as a separate cluster of nodes with isolated configuration.

### Aspect Configuration

Aspects are configured via `manifest.json` in the cloud portal repository:

```json
{
  "commerceSuiteVersion": "2211.24",
  "aspects": [
    {
      "name": "accstorefront",
      "properties": [
        {
          "key": "spring.session.enabled",
          "value": "true"
        },
        {
          "key": "cluster.node.groups",
          "value": "integration,yHotfolderCandidate"
        }
      ],
      "webapps": [
        {
          "name": "mystorefront",
          "contextPath": ""
        }
      ]
    },
    {
      "name": "backgroundProcessing",
      "properties": [
        {
          "key": "cluster.node.groups",
          "value": "integration,yHotfolderCandidate,backgroundProcessing"
        }
      ]
    }
  ],
  "extensions": ["mystorefront", "mycore"]
}
```

Key aspect config patterns:

- **cluster.node.groups**: controls which cronjobs run on which aspect
- **spring.session.enabled**: turns on HTTP session failover, which persists sessions to the database (`storedhttpsessions`) so a lost node does not log the shopper out
- **webapps**: which web applications deploy to this aspect (storefront, backoffice)

### CCv2 Build Process

CCv2 builds are triggered via Git push to the cloud portal repository. Build pipeline:

```mermaid
graph LR
    A[Git Push] --> B[Cloud Portal Webhook]
    B --> C[Build Server: ant clean all]
    C --> D[Docker Image Build]
    D --> E[Image Push to Registry]
    E --> F[Deployment to Environment]
    F --> G[Health Check]
    G --> H[Traffic Cutover]
```

Build stages:

1. **Source checkout**: Cloud portal clones the repository
2. **Ant build**: `ant clean all` compiles the platform and every extension in the build path
3. **Docker image**: Platform + extensions packaged into Docker image
4. **Image push**: Image pushed to CCv2 registry (GCR/ACR)
5. **Deployment**: Rolling deployment to target environment
6. **Health check**: the platform must answer before the load balancer admits traffic
7. **Traffic cutover**: Load balancer switches to new pods

Build artifacts:

- `hybris/bin/platform`: compiled platform
- `hybris/data`: initial data (ImpEx, media)
- `manifest.json`: aspect configuration
- `solr/`: Solr core config (if using embedded Solr)

### CCv2 Deployment Environments

CCv2 provides isolated environments for each stage of the SDLC:

| Environment | Purpose                                  | Refresh Strategy                        |
| ----------- | ---------------------------------------- | --------------------------------------- |
| Development | Feature development, integration testing | Database copy on request (Cloud Portal) |
| Staging     | Pre-production testing, UAT              | Database copy on request (Cloud Portal) |
| Production  | Live customer traffic                    | Blue/green deployment                   |

Each environment has:

- Dedicated database (Azure SQL)
- Dedicated Solr cluster (search index)
- Dedicated Azure Blob storage (media files)

### Environment Variables

CCv2 injects environment-specific config via environment variables:

```properties
# hybris/config/local.properties, for local development only.
# CCv2 runs on Azure SQL, so the driver is the Microsoft one.
db.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
db.url=jdbc:sqlserver://localhost:1433;databaseName=commerce
```

On CCv2 you do not set the datasource yourself. The platform receives it from the
environment, and the configuration you control arrives two ways:

- **`manifest.json`**: properties committed with the code, per aspect, and the
  `useConfig` block that points at property files in the repository
- **Cloud Portal service configuration**: environment-specific values, including
  secrets, held outside the repository

Anything a Kubernetes habit tells you to set as a pod environment variable belongs in
one of those two places instead.

## Data Model Patterns

### Product Model

Products in SAP Commerce are hierarchical:

- **Product** (base type): sku, name, description
- **VariantProduct** (extends Product): color, size variants
- **ApparelProduct** / **ElectronicsProduct**: domain-specific extensions

Products belong to **Catalogs** and **Categories**. Classification via **ClassificationClass** and **ClassificationAttribute** for faceted navigation.

Catalog versioning:

- **Staged**: content editing, not visible to customers
- **Online**: published content, customer-facing

### Price Model

Pricing is multi-dimensional via **PriceRow**:

```
PriceRow: product + user group + currency + unit + date range → price
```

Price calculation via **PriceFactory** and **PriceService**. Discounts and promotions run on the **Drools rule engine** (`ruleengineservices`, `promotionengineservices`), which compiles rules into a rule module and evaluates them against the cart.

Price resolution order:

1. User-specific price (B2B negotiated pricing)
2. User group price (customer segment)
3. Base price (fallback)

### Order Model

Order lifecycle:

1. **Cart** (`CartModel`): the shopping cart. It is a sibling of `OrderModel`, not a mode of it; both extend `AbstractOrderModel`.
2. **Order** (OrderModel submitted): placed order
3. **ConsignmentEntry**: fulfillment/shipment

Order calculation via **CalculationService** applies totals, taxes, and discounts in sequence:

1. Item prices
2. Discounts (order-level, line-level)
3. Delivery cost
4. Taxes
5. Payment cost

## Cluster Topology

CCv2 runs SAP Commerce in a clustered environment. Key clustering patterns:

### Session Replication

CCv2 does not provision a Redis instance, so the Spring Boot session stores you
may have used elsewhere are not on the menu. Two mechanisms carry the session:

| Mechanism | What it does | Where it applies |
| --------- | ------------ | ---------------- |
| Sticky sessions | The load balancer keeps a shopper on the node that holds their session | Always on, and the first line of defence |
| HTTP Session Failover | Spring Session persists the session to the database (`storedhttpsessions`) so another node can pick it up when one dies | Opt-in, per web application |

Enable failover per webapp rather than globally, because every persisted session is
a database write on the hot path:

```properties
spring.session.enabled=true
spring.session.yacceleratorstorefront.save=async
```

Sticky sessions alone lose the cart when a node restarts mid-deployment. Failover
costs write throughput. Pick per application, not per project.

### Media Storage

Media files (images, documents) must be shared across nodes:

- **On-premise**: Shared filesystem (NFS)
- **CCv2**: Azure Blob Storage or AWS S3

Azure Blob config:

```properties
media.default.url.strategy=azure
media.azure.storage.account.connection-string=${AZURE_STORAGE_CONNECTION_STRING}
media.azure.storage.container.name=commerce-media
```

### Task Engine

The Task Engine runs background jobs (cronjobs). In a cluster:

- Tasks are locked at the database level (distributed lock)
- Only one node executes a given task at a time
- Node groups control which aspect executes which cronjob

Node group assignment:

```properties
cluster.node.groups=integration,yHotfolderCandidate,backgroundProcessing
```

## Integration Patterns

### OCC (Omni Commerce Connect)

Standard REST API for headless storefronts:

- Base path: `/occ/v2/{baseSiteId}/`
- Endpoints: `/products`, `/carts`, `/users`, `/orders`
- OAuth2 authentication (client credentials, password grant)
- Extensible via custom controllers and DTOs

OCC endpoint example:

```
GET /occ/v2/electronics/products/1234?fields=FULL
Authorization: Bearer <token>
```

Response:

```json
{
  "code": "1234",
  "name": "Sample Product",
  "price": {
    "value": 99.99,
    "currencyIso": "USD"
  },
  "stock": {
    "stockLevel": 10
  }
}
```

### ImpEx

Data import/export DSL (Domain-Specific Language):

```
INSERT_UPDATE Product; code[unique=true]; name; catalogVersion(catalog(id),version)
; product123 ; "Sample Product" ; Default:Staged
; product456 ; "Another Product" ; Default:Staged

INSERT_UPDATE Category; code[unique=true]; name; catalogVersion(catalog(id),version)
; cat001 ; "Electronics" ; Default:Staged

INSERT_UPDATE CategoryProductRelation; source(code,catalogVersion(catalog(id),version)); target(code,catalogVersion(catalog(id),version))
; cat001:Default:Staged ; product123:Default:Staged
```

Used for:

- Initial data load (essential data, sample data)
- Migrations (data model changes)
- Test data setup (integration tests)
- Bulk operations (price updates, catalog sync)

### Event System

SAP Commerce publishes **Business Events** for async processing:

```java
@Component
public class OrderPlacedEventListener extends AbstractEventListener<OrderPlacedEvent> {

  @Resource
  private EmailService emailService;

  @Override
  protected void onEvent(OrderPlacedEvent event) {
    final OrderModel order = event.getOrder();
    emailService.sendOrderConfirmation(order);
  }
}
```

Events are:

- **Synchronous by default**: an event published on one node runs its listeners on
  the caller's thread. Only events implementing `ClusterAwareEvent` leave the node
  and go asynchronous, so a slow listener is your slow request.
- **Not transactional by default**: the event fires on the change, not on the
  commit. To wait for the commit, implement `TransactionAwareEvent` and set
  `publishOnCommitOnly`. Otherwise a rolled-back transaction has already told the
  rest of the system it happened.
- **In-memory**: the event bus holds nothing. A listener that is down when the event
  fires never sees it, and there is no replay. Where you need delivery guarantees,
  use webhooks or write your own audit record.

Common events:

- `OrderPlacedEvent`
- `ProductModifiedEvent`
- `CustomerRegisteredEvent`
- `CartModifiedEvent`

## Performance Considerations

### Caching

SAP Commerce uses multi-layer caching:

| Cache Type               | Mechanism          | Scope                      |
| ------------------------ | ------------------ | -------------------------- |
| **Region Cache**         | Ehcache            | Type system, catalogs, CMS |
| **FlexibleSearch Cache** | Query result cache | Read-heavy queries         |
| **CMS Page Cache**       | Pre-rendered pages | Storefront performance     |

Region cache sizes are set per *region*, not per extension. The region names are fixed by the platform (`entityregion`, `typesystemregion`, `querycacheregion` and so on):

```properties
regioncache.entityregion.size=2000000
regioncache.entityregion.evictionpolicy=LRU
```

### Database Optimization

- Use **FlexibleSearch** with proper indexing (not raw SQL)
- Avoid N+1 queries. Fetch relations in one query
- Partition large tables (`OrderEntry`, `PriceRow`, `CustomerReview`)
- Monitor slow queries via **DB Performance Monitoring** in HAC

Index example:

```sql
CREATE INDEX idx_product_code ON products(p_code);
CREATE INDEX idx_order_user ON orders(p_user);
```

### Clustering Best Practices

- **Session replication**: sticky sessions plus database-backed failover on the storefront webapp; there is no Redis on CCv2
- **Media storage**: External blob storage (Azure/S3), not filesystem
- **Task Engine**: Assign cronjobs to `backgroundProcessing` aspect only
- **Health checks**: CCv2 runs these for you; your job is to keep startup deterministic so a node is ready when it says it is
- **Logging**: Centralized logging (ELK, Splunk) for distributed tracing

## Next Steps

These deeper guides are in development. Topics planned:

- OCC API Integration Patterns
- Backoffice Customization
- Promotion Engine (CAP) deep dive
- Spartacus / Composable Storefront architecture
- CCv2 deployment troubleshooting
