BlueShop Recommendation System - As Built

Current-state technical overview for sharing.
Behavior and contracts are source-backed; transient deployment and pipeline snapshots are intentionally omitted.
Historical implementation intent remains available as RECOMMENDATION-PLAN.md and RECOMMENDATION-PLAN.html.

1. What BlueShop Delivers

BlueShop has a dedicated recommendation-service bounded context. It serves explainable product recommendations at four storefront placements:

Placement Customer experience Context sent to Recommendation
HOME Popular or personalized discovery Recently viewed products and, when authenticated, server-side purchase history
CART Complementary products before checkout Current cart product IDs
ORDER_CONFIRMATION Relevant next products after purchase Product IDs preserved from the completed cart
PDP_SIMILAR Semantically similar products The current product ID

The system combines five strategies:

Serving rereads Recommendation's local eligibility projection after the candidate cache. A present row is accepted only when it is published and its availability is not OUT_OF_STOCK; a missing row passes, and UNKNOWN also passes. The check therefore removes known unpublished or OUT_OF_STOCK candidates, but it is not fail-closed and event lag remains a serving risk.

2. Three Decision Layers

BlueShop does not use one universal recommendation score. It combines three decision layers with different scopes, inputs, and meanings:

Layer Question answered Current inputs Current strategies
Global What is broadly relevant now? Decayed order demand, category and featured-product facts POPULARITY
Product-to-product What belongs with or resembles this product set? Co-purchase pairs, curated relations, multilingual embeddings CO_PURCHASE, CURATED_RELATION, SIMILAR_CONTENT
Customer-to-product What is relevant to this specific customer? Purchase history and Catalog-persisted recently viewed products Interleaved PERSONAL_HISTORY and view-seeded SIMILAR_CONTENT on authenticated HOME
Recommendation architecture diagram 1

Global layer

The global layer is customer-independent. It provides a safe baseline for anonymous traffic, cold starts, and fallback capacity. Popularity is derived from order facts with time decay rather than from page-view volume.

Product-to-product layer

This layer starts from one or more seed products. It can express observed co-purchase behavior, explicit catalog-manager intent, or semantic similarity. It powers cart, order-confirmation, and PDP contexts and also contributes to HOME personalization.

Customer-to-product layer

This layer combines long-term and short-term customer context:

Customer-level decisioning does not put customer identity into measurement events. Recommendation uses the authenticated UUID only for serving, while served/clicked CloudEvents remain anonymous and no-PII.

3. System Context And Ownership

Recommendation architecture diagram 2

Ownership boundaries

Boundary Owns Recommendation keeps only
Catalog Products, lifecycle, categories, curated cross-sell/upsell relations Publication/category snapshots, relation projections, embedding source facts
Stock Authoritative availability and reservations Asynchronous availability projection and source freshness
Order Order lifecycle and commercial snapshots Order-product facts and customer purchase profile
Recommendation Candidate generation, ranking, serving policy, measurement Affinity, popularity, eligibility, relations, embeddings, inbox/outbox
Analytics Analytical facts and dashboards Item-grain served/clicked projections and CTR views

Recommendation never becomes authoritative for product, stock, order, or customer data. It projects the minimum facts needed to make a decision and rereads local eligibility before returning a result. That read rejects a present unpublished or OUT_OF_STOCK row, but missing and UNKNOWN state pass.

4. Public And Internal Contracts

The gateway exposes the service under /api/recommendation.

Operation Access Purpose
GET /v1/recommendations Public; optional JWT Serve one placement using up to 20 seed product IDs and at most 12 results
POST /v1/recommendations/clicks Public Accept a client-reported click beacon; request shape is validated, but membership in the served set is not
POST /internal/v1/recommendations/recompute admin role Refresh known catalog snapshots, embeddings, and derived projections

A recommendation response carries:

The API intentionally returns product IDs rather than duplicating Catalog DTOs. The storefront preserves recommendation order and hydrates cards through Catalog's bulk endpoint.

5. Event Ingestion And Derived Data

Recommendation architecture diagram 3

Two views of a purchase

Model Grain Question it answers
order_product_facts One order and one product What happened in this exact transaction?
customer_product_purchases One customer and one product What is this customer's accumulated purchase relationship with the product?

Delivery semantics

Data schema evolution

Recommendation owns eight Flyway migrations:

  1. Baseline schema and service RLS.
  2. Order-product facts and purchase profile.
  3. Eligibility and curated relations.
  4. Affinity and popularity scores.
  5. Transactional inbox.
  6. Separate catalog and availability freshness clocks.
  7. vector(384) product embeddings and HNSW index.
  8. Recommendation measurement outbox.

The vector PostgreSQL extension is installed by GitOps with elevated platform privileges; application Flyway only owns service schema objects.

6. Actual Serving Strategy

The historical plan contains several candidate chains considered during design. The deployed chains are the following code-backed behavior:

Context Actual ordered strategy chain
Anonymous HOME POPULARITY
Authenticated HOME, no purchases SIMILAR_CONTENT -> CURATED_RELATION -> POPULARITY
Authenticated HOME, with purchases Interleaved PERSONAL_HISTORY + SIMILAR_CONTENT -> CURATED_RELATION -> POPULARITY
CART CO_PURCHASE -> CURATED_RELATION -> POPULARITY
ORDER_CONFIRMATION CO_PURCHASE -> CURATED_RELATION -> POPULARITY
PDP_SIMILAR SIMILAR_CONTENT
Recommendation architecture diagram 4

Ranking details

Personal history

PERSONAL_HISTORY is a fallback sequence, not a weighted blend:

  1. Co-purchase neighbours of recent purchases.
  2. Customer-category popularity if no affinity result exists.
  3. Semantic neighbours of the purchase seeds if the first two lanes are empty.

7. Curated Recommendation Flow

Recommendation architecture diagram 5

Catalog owns the relation and its language. Recommendation owns serving and measurement. A curated target is removed when its local projection is present and says unpublished or OUT_OF_STOCK. Missing eligibility or UNKNOWN availability passes, so projection lag can still expose an unavailable target.

8. Semantic Recommendation Flow

Recommendation architecture diagram 6

Runtime model

Semantic text prioritizes structured product tags when present. Otherwise it combines localized name, description, short description, SKU, brand, and localized attribute values.

Semantic cold start does not require order history. A newly published product can receive an embedding from its Catalog event and immediately participate in PDP_SIMILAR once its snapshot and availability are current.

9. Storefront Integration

Recommendation architecture diagram 7

The Angular implementation follows BlueShop's frontend boundary rules:

10. Measurement And BI

Recommendation architecture diagram 8

Measurement contract

RecommendationServed records the anonymous set ID, placement, anonymous/authenticated request context, seed product IDs, ranked items, environment, traffic class, and generation time.

RecommendationClicked records the set ID, placement, product, one-based rank, strategy, environment, traffic class, and click time. The public request supplies the set ID, placement, product, rank, and strategy; the public traffic-class header is also caller-controlled and defaults to LIVE when absent or malformed. The service owns only environment and receipt time.

Neither event includes customer identity, contact data, address data, cost, or margin. The click endpoint validates field shape and enum parsing, but does not look up the served set or verify that the product, rank, placement, or strategy belonged to it. A conforming caller can therefore forge a tuple that ClickHouse later joins to a served tuple. These events are useful client instrumentation, not trustworthy proof of a human choice, causal impact, or customer identity.

Analytical model

Served measurement is deliberately non-blocking for the customer response: a measurement persistence error is logged but does not prevent recommendations from rendering. Click persistence is an explicit accepted request path, but its values remain client-reported.

11. Security, Privacy And Operations

Security

Operational cadence

12. Verification And Demonstrations

Verification surfaces

Embedded recommendation videos

These five players stay together as one Recommendation gallery and play directly from the local share package. Every film uses burned-in scene narration, so its business story remains understandable without audio:

PERSONALIZATION LOOP / 42.12S

Checkout to personalized recommendations

Shows a customer add a product, keep checkout customer-visible through address entry, place the order, receive clickable next-product recommendations that exclude the purchase, then return to a HOME strip recomposed from purchase history and recently viewed intent.

PURCHASE PROFILE / 47.92S

One order becomes personalization

The film visibly shows the real order, a later product view, and the resulting HOME strip. Its executable E2E response assertion, rather than labels on the product cards, verifies one PERSONAL_HISTORY result, one SIMILAR_CONTENT result, and exclusion of both starting products.

PRODUCT PERFORMANCE / 42.60S

What product click instrumentation was reported?

Shows product-level Recommendation BI: product name and SKU alongside impressions, client-reported clicks, CTR, average rank, placement, strategy, and engagement gaps, then isolates one accepted click tuple. It demonstrates instrumentation, not a trustworthy human choice.

CLASSIC BUSINESS LOOP / 73.36S

Recommendation: the complete business loop

Shows a catalog manager curating two related products, a stock adjustment projecting known OUT_OF_STOCK state and removing that candidate, and a customer following the eligible recommendation to its product page. It demonstrates the operational recommendation loop without an E2E-only BI diagnostic.

SEMANTIC COLD START / 88.12S

A new product finds its place

Visible UI evidence shows a newly eligible product receiving a "Similar products" strip. SIMILAR_CONTENT strategy, its explanation, and operation without purchase history are source- and BDD-backed behavior, not claims established by the film itself.

Source and executable evidence

Concern Source
HTTP boundary RecommendationController.java
Strategy chains FallbackChain.java
Candidate engine HeuristicRecommendationEngine.java
Serving-rule orchestration DefaultRecommendationApplicationService.java
Order facts and customer purchase profile R2dbcOrderFactRepository.java
Eligibility behavior EligibilityPolicy.java
Semantic inference OnnxProductTextEmbedder.java
Semantic SQL R2dbcSemanticSimilarityRepository.java
Measurement RecommendationMeasurementService.java
Public click request RecommendationClickRequest.java
Analytics projection RecommendationMeasurementProjectionService.java
Product-level BI view V023__recommendation_product_performance.sql
Storefront state recommendations.store.ts
Permanent browser journeys storefront-recommendations.spec.ts
Recommendation BDD recommendation-rules.feature
Traceable specification recommendation.spec.yaml

13. Delivered Versus Deferred

Capability State Notes
Dedicated recommendation bounded context Delivered Reactive Spring Boot service with service-owned schema and policies
HOME, CART, order confirmation and PDP placements Delivered One reusable storefront component and Signal Store
Co-purchase, popularity and purchase-history strategies Delivered Deterministic, explainable derived projections
Customer-level purchase and recently-viewed blending Delivered Authenticated HOME alternates long-term purchase history with short-term semantic browsing intent
Catalog-manager curated relations Delivered Catalog-owned source, Recommendation-owned serving projection
Semantic recommendations Delivered Local multilingual ONNX inference plus pgvector
Known publication and OUT_OF_STOCK filtering Delivered with limit Local projection is reread after cache lookup; missing and UNKNOWN eligibility pass
Missing or lagging eligibility Current serving risk The policy is not fail-closed, so event lag can expose an unavailable candidate
Served/client-reported click measurement and product-level Recommendation BI Delivered with trust limit No-PII pipeline is useful for instrumentation; click tuples are not verified against served sets
Gorse learned engine and A/B routing Deferred by design Current client-reported click data is not a trustworthy learned-engine gate
Elasticsearch More-Like-This adapter Not built pgvector shipped directly
Semantic fallback in CART Not implemented Actual chain is co-purchase, curated, popularity
Non-semantic fallback on PDP Not implemented Actual PDP chain is semantic-only; thin results hide the strip
Weighted blending across all strategies Not implemented Current engine uses ordered priority fill; only the two customer-level HOME signals are deterministically alternated
Infinite event replay as disaster recovery Not claimed Full historical recovery requires PostgreSQL backup plus retained Kafka replay

14. Result

The delivered BlueShop recommendation capability is not a single algorithm or UI carousel. It is a complete bounded context:

Phase 5 remains intentionally unbuilt. The current click stream cannot gate a learned engine because callers control the click tuple and traffic class. Such a gate requires server-side served-set validation, abuse controls, and experiment-quality evidence first.