Skip to main content

Recommendation Service

Overview

The Recommendation Service provides personalized product recommendations based on user behavior data. It stores user activities in DocumentDB and caches recommendation results via ElastiCache (Valkey) to ensure fast response times.

ItemValue
LanguagePython 3.11
FrameworkFastAPI
DatabaseDocumentDB (MongoDB compatible)
CacheElastiCache (Valkey)
Namespacemall-services
Port8000
Health CheckGET /health

Architecture

API Endpoints

Recommendation API

MethodPathDescription
GET/api/v1/recommendations/{user_id}Personalized recommendations
GET/api/v1/recommendations/trendingTrending products
GET/api/v1/recommendations/similar/{product_id}Similar product recommendations

Request/Response Examples

Personalized Recommendations

Request:

GET /api/v1/recommendations/user_001?limit=10

Response:

{
"user_id": "user_001",
"recommendations": [
{
"product_id": "prod_101",
"score": 0.95,
"reason": "Based on your browsing history",
"category": "electronics"
},
{
"product_id": "prod_205",
"score": 0.87,
"reason": "Based on your browsing history",
"category": "fashion"
},
{
"product_id": "prod_089",
"score": 0.82,
"reason": "Based on your browsing history",
"category": "electronics"
}
],
"generated_at": "2024-01-15T10:00:00Z"
}

Request:

GET /api/v1/recommendations/trending

Response:

{
"products": [
{
"product_id": "prod_001",
"name": "Samsung Galaxy S24",
"category": "electronics",
"score": 0.98,
"view_count": 15420,
"purchase_count": 2341
},
{
"product_id": "prod_042",
"name": "Nike Air Max",
"category": "fashion",
"score": 0.94,
"view_count": 12890,
"purchase_count": 1876
},
{
"product_id": "prod_078",
"name": "Apple AirPods Pro",
"category": "electronics",
"score": 0.91,
"view_count": 11200,
"purchase_count": 1543
}
],
"generated_at": "2024-01-15T10:00:00Z"
}

Similar Product Recommendations

Request:

GET /api/v1/recommendations/similar/prod_001?limit=10

Response:

{
"product_id": "prod_001",
"similar": [
{
"product_id": "prod_002",
"score": 0.89,
"reason": "Users who viewed this also viewed",
"category": "electronics"
},
{
"product_id": "prod_015",
"score": 0.76,
"reason": "Users who viewed this also viewed",
"category": "electronics"
},
{
"product_id": "prod_023",
"score": 0.71,
"reason": "Users who viewed this also viewed",
"category": "accessories"
}
],
"generated_at": "2024-01-15T10:00:00Z"
}

Data Models

Recommendation

class Recommendation(BaseModel):
product_id: str
score: float = Field(ge=0.0, le=1.0) # 0.0 ~ 1.0
reason: str # Recommendation reason
category: Optional[str] = None

UserActivity

class UserActivity(BaseModel):
user_id: str
product_id: str
action: str # view, click, purchase, add_to_cart
timestamp: datetime
metadata: Optional[dict] = None

TrendingProduct

class TrendingProduct(BaseModel):
product_id: str
name: str
category: str
score: float
view_count: int
purchase_count: int

RecommendationResponse

class RecommendationResponse(BaseModel):
user_id: str
recommendations: list[Recommendation]
generated_at: datetime

TrendingResponse

class TrendingResponse(BaseModel):
products: list[TrendingProduct]
generated_at: datetime

SimilarProductsResponse

class SimilarProductsResponse(BaseModel):
product_id: str
similar: list[Recommendation]
generated_at: datetime

Recommendation Algorithms

Activity Weights

ActionWeightDescription
purchase1.0Purchase completed
add_to_cart0.7Added to cart
click0.3Product clicked
view0.1Product viewed

Personalized Recommendation Logic

def _generate_recommendations(activities: list[dict], limit: int) -> list[Recommendation]:
product_scores: dict[str, float] = {}
action_weights = {
"purchase": 1.0,
"add_to_cart": 0.7,
"click": 0.3,
"view": 0.1
}

for activity in activities:
product_id = activity.get("product_id")
action = activity.get("action", "view")
weight = action_weights.get(action, 0.1)
product_scores[product_id] = product_scores.get(product_id, 0) + weight

sorted_products = sorted(product_scores.items(), key=lambda x: x[1], reverse=True)[:limit]

return [
Recommendation(
product_id=pid,
score=min(score / 10.0, 1.0),
reason="Based on your browsing history"
)
for pid, score in sorted_products
]

Caching Strategy

ElastiCache (Valkey) Key Structure

Key PatternDescriptionTTL
recommendations:{user_id}Personalized recommendation results1 hour
recommendations:trendingTrending products list1 hour
recommendations:similar:{product_id}Similar products list1 hour
leaderboard:popularPopular products sorted setReal-time

Cache Logic

CACHE_TTL_SECONDS = 3600  # 1 hour

async def get_personalized_recommendations(user_id: str, limit: int = 10):
cache_key = f"recommendations:{user_id}"

# Check cache
cached = await valkey.get_json(cache_key)
if cached:
return RecommendationResponse(**cached)

# Generate recommendations
activities = await repo.get_user_activities(user_id)
recommendations = _generate_recommendations(activities, limit)

response = RecommendationResponse(
user_id=user_id,
recommendations=recommendations,
generated_at=datetime.utcnow()
)

# Store in cache
await valkey.set_json(cache_key, response.model_dump(mode="json"), CACHE_TTL_SECONDS)

return response

Environment Variables

VariableDescriptionDefault
SERVICE_NAMEService namerecommendation
PORTService port8080
AWS_REGIONAWS regionus-east-1
REGION_ROLERegion role (PRIMARY/SECONDARY)PRIMARY
DB_HOSTDocumentDB hostlocalhost
DB_PORTDocumentDB port27017
DB_NAMEDatabase namerecommendations
DB_USERDatabase usermall
DB_PASSWORDDatabase password-
DOCUMENTDB_HOSTDocumentDB hostlocalhost
DOCUMENTDB_PORTDocumentDB port27017
CACHE_HOSTElastiCache hostlocalhost
CACHE_PORTElastiCache port6379
KAFKA_BROKERSKafka broker addresslocalhost:9092
LOG_LEVELLog levelinfo

Service Dependencies

Services It Depends On

  • DocumentDB: User activity data storage
  • ElastiCache (Valkey): Recommendation result caching, popular products leaderboard
  • Product Catalog: Product metadata lookup

Services That Depend On This

  • API Gateway: Display recommendations on home/product pages
  • Search Service: Apply personalization to search results

Feature Details

  • Based on views/purchases in the last 24 hours
  • Real-time ranking managed via ElastiCache Sorted Set
  • Key: leaderboard:popular

Similar Product Recommendations

  • Based on "customers who viewed this also viewed"
  • Collaborative filtering algorithm applied
  • Prioritizes products in the same category

Diversity Guarantee

  • Prevents more than 3 consecutive products from the same category
  • Excludes already purchased products