00 — Replatforming Program Overview¶
The starting point for understanding the Replatforming program. Explains what we're building, why, how we're structuring the work, and where we are today. Intended for new team members, stakeholders, and anyone needing the full picture in one place.
Last validated: 2026-07-01 — against live GCP
platform-dev-p01, Jira (project = PLT, all 42+ Replatforming epics), theevo-dtoflow-protoscentral-documentation branch, and the actual service code (platform-evaluation-engine,platform-image-render-service).
1. What Is Replatforming?¶
Pricer AB sells an Electronic Shelf Label (ESL) platform to retail chains. Today, each store runs its own instance of Pricer Server (R3Server) — a Java monolith with its own MySQL database, deployed as a Kubernetes "Store-Unit." A retail chain (a tenant) is just a collection of these Store-Units.
The problem: Per-store instances don't scale. A price change across 200 stores means 200 independent updates. Item data, rendering, and link management are all duplicated. Adding a new feature means deploying to thousands of Store-Units.
The solution — Replatforming: Move item storage, link management, rendering, and business APIs off the per-store instances and into a shared, multi-tenant cloud platform called DTOflow on Google Cloud (Cloud Run + Spanner + Pub/Sub). The only thing that stays on R3Server is what must stay — the radio transmission engine that drives the physical ESL labels via IR/RF.
One sentence: Replatforming migrates everything except the transmission engine from per-store monoliths to a shared event-driven cloud platform.
2. The Three Phases¶
| P0: Prove It | P1: Ship It | P2: Scale It | |
|---|---|---|---|
| Goal | Prove the cloud pipeline works without touching real labels | One real, revenue-generating tenant live on the cloud path | All tenants migrated, full feature parity with R3Server |
| Tenants | Internal dev tenants (Replatforming-Dev, Evo-Se, Application-Stage) | byPricer → small customer → medium customer | All remaining tenants |
| Risk | Zero — Shadow Mode runs in parallel, label transmit is dropped | Controlled — per-API-path routing enables incremental migration and rollback | Managed — each tenant validated before the next |
| Output | Cloud pipeline produces 100% identical images to the edge, validated for 24h on 3 tenants | First customer runs on DTOflow. R3Server is thin edge (transmission only). | DTOflow replaces R3Server for all non-transmission functions. |
| Prerequisites | DTOflow infrastructure live (Spanner, Pub/Sub, CQS, Cloud Run) | P0 closed. Item APIs + per-API-path routing live. Tenant isolation proven. | P1 closed. All features built. Ops readiness complete. |
| Target | Week 34 (Aug 17-23, 2026) | W38: byPricer · W44: ops ready · Q1 2027: all 3 tenants | 2027 — scoped after P1 closes |
Phase 0: Prove It¶
What we're building: The cloud infrastructure and proving it can process real data from R3Server without affecting real labels. This is called Shadow Mode — the cloud pipeline runs in parallel with the edge, receiving live item/link data, processing it through evaluators and renderers, but dropping the transmission to labels. We compare cloud-rendered images against edge-rendered images — they must be 100% identical for 24 continuous hours on three tenants.
Prerequisites before Phase 0 can close: - All export data pipes live (items, links, ECC params, ESL status, itemproperties) - CQS (ChangeQueueService) operating and services self-subscribing - Per-API-path routing (PLT-2101) not required for Phase 0, but must be started before Phase 1 - CQS client in R3Server (PLT-1870) live - 24h image parity on all 3 Shadow Mode tenants
Acceptance criteria: 24 continuous hours of 100% rendered-image parity across Replatforming-Dev, Evo-Se, and Application-Stage tenants. Zero label impact.
Phase 1: Ship It¶
What we're building: The item API surface (PLT-2378, PLT-2651), tenant isolation (PLT-2578), operational readiness (monitoring, load testing, DR, runbooks), and the tenant migration mechanism (per-API-path routing).
Prerequisites before Phase 1 can start: - Phase 0 closed (Shadow Mode parity confirmed) - Item property validation (PLT-2651) — the single clearest gate. 4 of 5 item pipeline services are built; this is the missing piece. - Item Patch APIs (PLT-2378) — gates Plaza Mobile and Central-Manager item paths - Per-API-path routing (PLT-2101) — the mechanism that makes migration incremental - Tenant isolation proven (PLT-2578) — non-negotiable before real customer data enters
Acceptance criteria: byPricer (demo tenant) live on DTOflow. Then one small customer (e.g., Landwaart AGF, 2 stores, sub-1000 labels). Then one medium customer (e.g., spar-be, O(10) stores, ~13K labels). Each tenant stable for 2 weeks before the next. R3Server is thin edge (transmission only) for migrated tenants.
Phase 2: Scale It¶
What we're building: Full feature parity with R3Server — timed item updates, ECC rendering parity, segment labels, auto-unlink, flash APIs, subscription system, webhooks. Plus auto-scaling and SLA support.
Acceptance criteria: All remaining tenants migrated. All features built. R3Server is transmission-only for all tenants.
3. How We're Structuring the Work¶
Each Phase decomposes into Milestones (~6 weeks, a major thematic target), which decompose into Increments (2-4 weeks, a demonstrable end-to-end scenario ending in a specific demo), which contain Epics (Jira units, assignable and trackable).
| Level | Timescale | Answers | Example |
|---|---|---|---|
| Phase | 6-12 months | When in the program? | P0: Prove It |
| Milestone | ~6 weeks | What major target? | M2: Shadow Mode Validation |
| Increment | 2-4 weeks | What can we demo by Friday? | Inc 2.1: Core Data Tap |
| Epic | Sprint | What Jira unit is tracked? | PLT-2483: storeitemvalues export |
The 6 Milestones¶
| Phase | Milestone | Goal | Status | Target |
|---|---|---|---|---|
| P0 | M1: Platform Foundation | Core infrastructure live and certified | 🟡 Active | W31 (Aug 2) |
| P0 | M2: Shadow Mode Validation | Cloud pipeline runs in parallel with edge. Zero label risk. | 🟡 Active | W34 (Aug 23) |
| P1 | M3: First Tenant Go-Live | Item and link API traffic cut over to cloud | 🔴 Gated | W38 (Sep 20) |
| P1 | M4: Production Hardening | Monitoring, load testing, DR, runbooks | 🔵 Not started | W44 (Nov 1) |
| P2 | M5: Feature Parity | Timed updates, ECC sync, autoscaling, SLAs | 🔵 Not started | 2027 |
| P2 | M6: Full Migration | All tenants migrated | 🔵 Not started | 2027 |
Phase 0 Increments¶
| Milestone | Inc | Name | Demo | Status | Target |
|---|---|---|---|---|---|
| M1: Platform Foundation | 1.1 | Core Event Routing | Dummy DTO → CQS → Cloud Run queue | 🟡 Active | W29 (Jul 19) |
| 1.2 | Internal Comm & Security | R3Server ↔ cloud CQS bridge + PSC + PROD certification | 🟡 Active | W31 (Aug 2) | |
| M2: Shadow Mode Validation | 2.1 | Core Data Tap | Price update in R3 → all DTOs appear in Spanner | 🟡 Active | W30 (Jul 26) |
| 2.2 | Shadow Mode Completion | Item change → cloud render → transmit dropped | 🟡 Active | W32 (Aug 9) | |
| 2.3 | API Parity Validation | Extend API dev to cover Basic Functionality | 🔵 Not started | W33 (Aug 16) | |
| 2.4 | Routing | Per-API-path routing (PLT-2101) | 🔵 Not started | W34 (Aug 23) |
Every Increment ends with a named demo scenario — a specific, verifiable outcome that can be shown in a sprint review.
4. The Target Architecture¶
The end state is a hybrid cloud-edge system:
☁️ Cloud (DTOflow) 🏬 Edge (R3Server, thin)
┌─────────────────────────┐ ┌──────────────────────┐
│ Item storage (Spanner) │ │ Transmission engine │
│ Link management │ │ Basestation control │
│ Rendering (Studio/ECC) │──images──→ │ Flash & display-page │
│ Work dispatch (CQS) │ │ Store map / geo │
│ APIs & Gateway (Apigee) │ │ Local ESL status/ACKs │
└─────────────────────────┘ └──────────────────────┘
What moves to cloud¶
- Item storage: per-store MySQL → Spanner
storeitemvalues - Item/Link APIs: R3Server REST →
item-registry-api,link-registry - Rendering: per-Store-Unit CPU →
platform-image-render-service(Studio),ecc-renderer(ECC) - Design resolution:
studio-link-evaluatorevaluates CEL rules from CommunicationPacks against item properties - Work dispatch: R3Server internal → CQS subscription fan-out (GKE)
What stays on R3Server (by design, never migrates)¶
- Transmission engine — millisecond IR/RF to ESLs; cannot be remote
- Basestation control — physical radio hardware management
- Flash & display-page — real-time commands requiring sub-second latency
- Store map / geo — physical store layout, tied to basestation positions
How migration is incremental¶
Per-API-path routing (PLT-2101) teaches ingress-nginx to route by URL path:
- /api/.../items/* → Cloud Run item-registry-api
- /api/.../links/* → Cloud Run link-registry
- /api/private/* (transmission, flash, display-page, map) → R3Server Store-Unit
This means individual API paths can be flipped independently — and rolled back by flipping them back. No client change required.
5. How the Cloud Platform Works¶
DTOflow is a decentralized, event-driven platform. There is no central orchestrator.
The data backbone¶
Service writes DTO to Spanner
→ Pub/Sub emits dtoflow-changes-<dto>.v1
→ ChangeQueueService (CQS) delivers to all subscribing services
→ Each service dequeues independently, fetches the DTO, processes it
→ May write its own output DTOs → triggers further subscribers
The 5 core data flows¶
| Flow | What happens | Status |
|---|---|---|
| Item price change → label update | item-registry writes storeitemvalues → evaluator re-evaluates CEL rules in CommunicationPack (may write new studiolink) → renderer reads designerlink, design from LFS, item properties → renders label via fabric.js → writes renderedimage → pricer-server transmits to ESL |
🟡 Partially ready (gated by PLT-2651) |
| Link creation → render | link-registry writes link.v2 + storeesl → evaluator resolves design (or uses forced_design_id directly) → writes studiolink → renderer produces image |
🟢 Live |
| Design publication → mass re-render | studio-design-library writes design.v1 → renderer finds all affected designerlink records via by_design alias → re-renders every one |
🟢 Live |
| CommunicationPack change → mass re-evaluation | CP scenario tree changes → evaluator reads ALL studio links for the tenant → re-evaluates CEL rules for every link → writes new studiolink for any changed design |
🟢 Live |
| Item deletion → label clear | item-registry tombstones storeitemvalues → evaluator detects tombstone → triggers unlink → renderer produces blank label |
🔴 Not built |
The evaluator: how designs get chosen¶
The studio-link-evaluator (platform-evaluation-engine, Java) subscribes via CQS to storeitemvalues.v1, link.v2, and communicationpack.v1. When triggered:
- Depth-first traverses the CommunicationPack scenario tree
- Each scenario has a
cel_expression(Google's Common Expression Language) - CEL expressions reference
item.Price,item.Category,link.location,device.plType - Expressions from parent scenarios accumulate with
&& - First matching scenario wins — its
design_idsbecome the resolved designs - Designs are filtered by ESL type compatibility
- If the resolved design differs from the current
studiolink.design_id, a newstudiolinkis written
If a link has forced_design_id set, the evaluator skips rule evaluation entirely — that design is used unconditionally.
The renderer: how labels get drawn¶
The platform-image-render-service (TypeScript, Node.js) receives Pub/Sub push events for designerlink.v1, storeitemvalues.v1, design.v1, canvasdesign.v1, and storeesl.v1. When triggered:
- Reads the
designerlinkDTO → extractsdesignId - Reads the
storeitemvaluesDTO → extractscustomPropertiesas a key-value map - Reads the design DTO → gets
jsonFilePathin LFS → reads the design JSON from GCS - The design JSON contains
svgDesign.svgBase64Encoded— either an SVG string or Fabric JSON - Parses the SVG via fabric.js and applies
propertyMappings— substituting item data (item.Price,item.Name) into SVG text elements - Registers fonts from DTOflow font DTOs
- Creates a Fabric Canvas, renders to PNG via
canvas.toDataURL() - Applies dithering for e-paper color reduction
- Writes PNG to LFS:
renderer/t/{tenantId}/eslimages/{sha256}.png - Writes
renderedimage.v1DTO with idt/{tenantId}/s/{storeId}/esls/{barcode}/pages/0/renderedimage
6. Current Status (2026-07-01)¶
What's live¶
- 21 Cloud Run services deployed in GCP
platform-dev-p01(europe-north1) - Spanner: instance
dtoflow(29 DTO tables, 1000 PU) +item-registry(1 table) - Pub/Sub: 32 topics
- Link creation → render → transmit: end-to-end live
- Design publication → mass re-render: live
- CommunicationPack change → mass re-evaluation: live
- ECC rendering: live (ecc-renderer, ecc-link-projector, esl-image-merger)
What's blocked (the gates)¶
| Epic | What | Why it matters |
|---|---|---|
| PLT-2651 | Item property validation | 🔴 Blocked, Unassigned. 4 of 5 item pipeline services built. This is the single clearest gate — without it, items can't be validated before Spanner write. |
| PLT-2378 | Item Patch APIs | 🔴 Blocked, Unassigned. Gates Plaza Mobile PATCH /items and Central-Manager bulk item paths. |
| PLT-2101 | Per-API-path routing | 🟡 Selected, Saikiran on vacation. The mechanism that makes migration incremental. |
What's on the critical path¶
- Daniel Pettersson owns PLT-2354 (Shadow Mode orchestration, realistically a 5-week task, not the 1w 2d currently estimated) — he is on the critical path
- Bart De Boer owns 4 active Phase 0 epics plus early Phase 2 work — overloaded
- 4 export epics (PLT-2496, 2495, 2488, 2714) are unassigned — invisible work sitting idle
- PLT-2601 (First Tenant Selection) is in Backlog — a business decision, not engineering
Timeline projection¶
| Date | Milestone |
|---|---|
| Week 34 (Aug 17-23, 2026) | Phase 0 close — all M2 increments complete |
| Week 38 (Sep 14-20, 2026) | First Phase 1 tenant (byPricer) live on DTOflow — M3 closed |
| Week 44 (Oct 26-Nov 1, 2026) | M4 closed — ops readiness complete |
| Q1 2027 | Phase 1 complete — small + medium customer live |
| 2027 | Phase 2 — full feature parity, all tenants migrated |
7. The Full Epic Map¶
All Replatforming epics mapped to their Milestone and Increment. See doc 15 for live status.
M1: Platform Foundation (P0 — Active)¶
| Inc | Epics | Target week |
|---|---|---|
| 1.1 Core Event Routing | PLT-2294 (Closed), PLT-169 (CQS), PLT-2792 (services own queues), PLT-2478 (PS ↔ CQS design) | 29 |
| 1.2 Internal Comm & Security | PLT-1870 (CQS client in R3Server), PLT-2336 (PSC), PLT-2118 (DTOflow PROD-ready) | 31 |
Acceptance criteria: all deliveries dependeing strictly on the new platform will be delivered to Prod.
M2: Shadow Mode Validation (P0 — Active)¶
| Inc | Epics | Target week |
|---|---|---|
| 2.1 Core Data Tap | PLT-2353, 2483, 2496, 2494, 2495, 2492, 2488, 2714 (8 export pipes) | 30 |
| 2.2 Shadow Mode Completion | PLT-2497 (Closed), PLT-2354 (Shadow Mode orchestration), PLT-2359(ECC Rendering Support) | 32 |
| 2.3 API Parity Validation | PLT-2966 (new), PLT-2357 (Linked Item APIs — Items), PLT-2358 (Linked Item APIs — Devices) | 33 |
| 2.4 Routing | PLT-2101 (per-API-path routing) | 34 |
M3: First Tenant Go-Live (P1 — Gated)¶
| Inc | Epics | Target week |
|---|---|---|
| Inc 1: Item+Link APIs | PLT-2651 (validation), PLT-2378 (Patch APIs), PLT-2274 (SIC), PLT-171 (SLA), PLT-2658 (LFS protection), PLT-2360/2361/2350/2356/2363/2352 (features) | 36 |
| Inc 2: Security & Isolation | PLT-2578 (tenant isolation), PLT-170 (write protection) | 37 |
| Inc 3: Tenant Switch | PLT-2601 (tenant selection), PLT-2572/2575 (store onboarding), PLT-2600 (studio readiness), PLT-2430 (integration tests) | 38 |
M4: Production Hardening (P1 — Not started)¶
| Inc | Epics | Target week |
|---|---|---|
| Inc 1: Monitoring | PLT-2579 (dashboards), PLT-2444 (status reporting) | 41 |
| Inc 2: Load Test | PLT-2576 (load testing), PLT-2369 (auto-scaling) | 42 |
| Inc 3: DR & Runbook | PLT-2599 (cutover runbook), PLT-2580 (DR), PLT-2581 (operational runbooks) | 44 |
M5: Feature Parity (P2 — Not started)¶
19 epics including PLT-2359 (ECC Links & Rendering), PLT-2350 (Timed Updates), PLT-2361 (Segment Labels), PLT-2360 (Unified Linking), PLT-2363 (Auto Unlink), PLT-2355 (Label Status APIs), PLT-2428 (Subscription System), PLT-171 (SLA), PLT-170 (Write Protection), PLT-2444 (Status Reporting), PLT-2369 (Auto-scaling).
M6: Full Migration (P2 — Not started)¶
Not yet scoped. Will be defined when M5 is underway.
8. Key Risks¶
| Risk | Severity | Detail |
|---|---|---|
| PLT-2651 + PLT-2378 unassigned | 🔴 Critical | Two blocked, unassigned epics gate the entire item pipeline. The single highest-priority action in the program. |
| PLT-2354 underestimated | 🔴 High | Shadow Mode orchestration estimated at 1w 2d — realistically 5w. Daniel Pettersson is on the critical path. |
| Summer vacation season | 🟡 High | July-August in Sweden. 32 working days to mid-August assumes 100% attendance. |
| Bart De Boer overloaded | 🟡 High | 4+ active epics across M1, M2, and M5. Risk of burnout and quality degradation. |
| Ops readiness entirely in Backlog | 🟡 Medium | Monitoring, DR, load testing, cutover runbook — all 11 M4 epics are in Backlog. Cannot put a real customer on the platform without these. |
9. How to Read the Full Doc Set¶
| Doc | What it covers |
|---|---|
| 00 (this doc) | Program overview — the starting point |
| 01 | Current Pricer platform architecture (before Replatforming) |
| 02 | What a tenant is, isolation model |
| 03 | Deep dive into Replatforming: phases, Shadow Mode, epic backlog |
| 04 | Target EVO/DTOflow architecture, hybrid boundary |
| 05 | Core concepts: links, tenants, EVO tokens, PCS |
| 08 | DTOflow platform: Spanner, Pub/Sub, CQS, service inventory |
| 11 | Link pipeline: link-registry, evaluator, link types |
| 12 | Rendering pipeline: studio-renderer, ecc-renderer, mergers |
| 13 | 5 core end-to-end data flows with Mermaid diagrams |
| 14 | Tenant migration process, switch procedure |
| 15 | Live status — all 58 epics mapped to Milestones and Increments |
| 17 | Phase 1 plan: feature delivery, gaps, tenant strategy |
| 19 | Delivery framework evolution (A/B/C → Phase→Milestone→Increment→Epic) |
| 20 | Phase 0 effort estimation analysis, mid-August deadline assessment |
Refresh sources: - GCP:
gcloud run services list --region=europe-north1 --project=platform-dev-p01- Jira:project = PLT AND issuetype = Epic AND labels in ("replatforming-phase-0","replatforming-phase-1","replatforming-phase-2") ORDER BY status ASC- GitHub:PricerAB/platform-evaluation-engine,PricerAB/platform-image-render-service,PricerAB/evo-dtoflow-protos