Skip to content
Back to case studies
SanitizedMigration2023

Discovery & Loyalty Platform

PHP monolith with static feeds → serverless discovery on Lambda, DynamoDB, and GraphQL; 3x throughput, +18% CTR and +22% DAU via Amazon Personalize.

Role
Senior Software Engineer
Context
Discovery / Loyalty (Indonesia)
Duration
Part of the 2022 to 2023 Imaginato engagement
Team
Senior engineer (me) + product and data partners

Tech stack

  • AWS Lambda
  • DynamoDB
  • GraphQL
  • Amazon Personalize
  • Node.js
  • API Gateway
  • EventBridge
  • S3
Executive summary

Business problem and production context.

Business problem

Qraved's discovery and loyalty product ran on a PHP monolith that could not keep up with catalog growth or personalized feeds. Recommendations were static, infra cost scaled faster than traffic, and engagement metrics had plateaued.

Architecture decision

Migrated the read-heavy services to serverless on Lambda, DynamoDB, and a GraphQL API, then wired Amazon Personalize into the discovery feed and loyalty prompts. Personalization ran off event streams so recommendations updated with real user behavior instead of nightly batches.

AWS production path

Reference architecture Rahul reviews before changing services.

ap-south-1 · us-east-1

AWS

AWS Account / prod

Region-aware · explicit failure, cost, and rollback controls

Edge and API ingress

public boundary
Users / clients
Route 53 icon

Route 53

DNS + health checks

CloudFront icon

CloudFront

edge cache

AWS WAF icon

AWS WAF

request filtering

API Gateway icon

API Gateway

public API boundary

Private workload boundary

blast radius visible
Lambda icon

Lambda

sync handler

SQS icon

SQS

buffer + retries

Lambda icon

Lambda

worker

DynamoDB icon

DynamoDB

state + access pattern

GenAI and data services

retrieval + cost path
Bedrock icon

Bedrock

model call

OpenSearch icon

OpenSearch

vector / keyword search

ElastiCache icon

ElastiCache

semantic cache

Control plane

cross-cutting
IAM least privilege
KMS encryption
CloudWatch metrics/logs
X-Ray traces
DLQ alarms
AWS Budgets
CloudTrail audit
Lambda aliases rollback
LegendData flowLive signalControl / policy

High availability

Multi-AZ, health checks, graceful failover

Data durability

Encrypted state, point-in-time recovery, backups

Security

IAM least-privilege, KMS, WAF, secret rotation

Observability

Logs, metrics, traces, alarm budgets

Automation

IaC, deploy pipelines, rollback in <30s

Cost control

Budgets, caching, tiered storage, idle off

What Rahul owned

The useful proof is the decision surface, not only the result number.

These are the parts of the work that show production judgment: ownership, constraints, rollback, cost, and observability.

Owned scope

  • Production architecture review, implementation sequencing, and operational handoff

Evidence artifacts

Sanitized production proofRisk reviewOperating notes
Constraints

What would fail first?

Every project has constraints. The useful work is naming them early enough that rollback, cost, and ownership are designed before an incident.

Production risk

The work needed explicit decisions around cost, reliability, rollback, and ownership.

Decision table

Trade-offs accepted on purpose.

Option
Decision
Reason
Amazon Personalize vs a hand-rolled model
chose Personalize to ship engagement gains fast without standing up an ML platform
Amazon Personalize vs a hand-rolled model: chose Personalize to ship engagement gains fast without standing up an ML platform.
GraphQL vs REST
GraphQL let mobile clients fetch discovery and loyalty data in one round trip, cutting chatty calls
GraphQL vs REST: GraphQL let mobile clients fetch discovery and loyalty data in one round trip, cutting chatty calls.
DynamoDB vs relational
single-table DynamoDB for predictable latency on the read-heavy discovery feed
DynamoDB vs relational: single-table DynamoDB for predictable latency on the read-heavy discovery feed.
Risk table

Production risks and how they were controlled.

Risk
Mitigation
Owner
Production behavior stayed unclear
Mapped the risky path, made owners visible, and shipped reversible improvements.
Platform / service owner
Implementation approach

Small steps, visible changes, fewer surprises.

  1. 01

    Mapped the monolith's discovery and loyalty flows, isolating the read-heavy feed and reward endpoints that drove most of the load.

  2. 02

    Stood up a GraphQL API in front of Lambda resolvers backed by DynamoDB single-table access patterns for predictable latency.

  3. 03

    Streamed interaction events through EventBridge into Amazon Personalize so the recommendation model learned from live behavior.

  4. 04

    Rolled personalization out behind a flag, comparing CTR and DAU against the static baseline before full cutover.

  5. 05

    Added cost and quality guardrails so the personalization layer stayed within budget as traffic grew.

Result

Before and after.

Discovery Throughput
baseline
3x
Infra Cost
baseline
about 30% lower
Click-Through Rate
baseline
+18% (Personalize)
Daily Active Users
baseline
+22%

Rollback path

Changes were kept small enough to reverse and visible enough to debug.

Cost considerations

Cost drivers were reviewed against real usage rather than generic service advice.

Observability notes

Signals were tied to user impact, owner action, and the failure mode being controlled.

Related services

Forward Deployed AI EngineeringAWS Production Architecture ReviewGenAI / RAG Production Readiness

Have a similar production problem?

Send the current architecture, bill concern, deployment pain, or GenAI reliability issue. I will help you find the first real bottleneck.