Created
June 16, 2026 06:01
-
-
Save azell/49e748c2a2e2073887648773e67ba4b7 to your computer and use it in GitHub Desktop.
mermaid-img.svg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <svg width="680" viewBox="0 0 680 820" xmlns="http://www.w3.org/2000/svg" role="img"> | |
| <title>CTA After Architecture v5</title> | |
| <desc>Web and mobile clients call the CTA Service. CTA Service calls Apollo GraphQL Router, which routes to the CTA Content Orchestrator. The orchestrator has a DynamoDB store, exposes a personalization API to content services, fans out via the router to 4 content services, and publishes events to Kafka which Databricks consumes for analytics and ML.</desc> | |
| <defs> | |
| <marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"> | |
| <path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> | |
| </marker> | |
| <style> | |
| text { font-family: Arial, Helvetica, sans-serif; fill: #1a1a1a; } | |
| .th { font-size: 14px; font-weight: 600; } | |
| .ts { font-size: 12px; font-weight: 400; fill: #444; } | |
| .c-gray rect { fill: #F1EFE8; stroke: #5F5E5A; } | |
| .c-teal rect { fill: #E1F5EE; stroke: #0F6E56; } | |
| .c-teal text { fill: #085041; } | |
| .c-purple rect { fill: #EEEDFE; stroke: #534AB7; } | |
| .c-purple text { fill: #26215C; } | |
| .c-amber rect { fill: #FAEEDA; stroke: #854F0B; } | |
| .c-amber text { fill: #412402; } | |
| .c-blue rect { fill: #E6F1FB; stroke: #185FA5; } | |
| .c-blue text { fill: #042C53; } | |
| .c-coral rect { fill: #FAECE7; stroke: #993C1D; } | |
| .c-coral text { fill: #4A1B0C; } | |
| .c-green rect { fill: #EAF3DE; stroke: #3B6D11; } | |
| .c-green text { fill: #173404; } | |
| .arr { fill: none; stroke: #888; stroke-width: 1; marker-end: url(#arrow); } | |
| </style> | |
| </defs> | |
| <!-- Background --> | |
| <rect width="680" height="820" fill="#ffffff"/> | |
| <!-- ── Clients ── --> | |
| <g class="c-gray"> | |
| <rect x="130" y="20" width="120" height="44" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="190" y="42" text-anchor="middle" dominant-baseline="central">Web client</text> | |
| </g> | |
| <g class="c-gray"> | |
| <rect x="310" y="20" width="120" height="44" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="370" y="42" text-anchor="middle" dominant-baseline="central">Mobile client</text> | |
| </g> | |
| <!-- Clients → CTA Service --> | |
| <line x1="210" y1="64" x2="255" y2="114" class="arr" marker-end="url(#arrow)"/> | |
| <line x1="370" y1="64" x2="305" y2="114" class="arr" marker-end="url(#arrow)"/> | |
| <!-- ── CTA Service ── --> | |
| <g class="c-teal"> | |
| <rect x="120" y="114" width="320" height="56" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="280" y="136" text-anchor="middle" dominant-baseline="central">CTA service</text> | |
| <text class="ts" x="280" y="156" text-anchor="middle" dominant-baseline="central">4,000 req/s · 250 ms budget · direct from clients</text> | |
| </g> | |
| <!-- CTA Service → Router --> | |
| <line x1="280" y1="170" x2="280" y2="216" class="arr" marker-end="url(#arrow)"/> | |
| <!-- ── Apollo GraphQL Router ── --> | |
| <g class="c-purple"> | |
| <rect x="140" y="216" width="280" height="56" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="280" y="238" text-anchor="middle" dominant-baseline="central">Apollo GraphQL router</text> | |
| <text class="ts" x="280" y="258" text-anchor="middle" dominant-baseline="central">Routes requests — used at both layers</text> | |
| </g> | |
| <!-- Router → Orchestrator --> | |
| <line x1="280" y1="272" x2="280" y2="318" class="arr" marker-end="url(#arrow)"/> | |
| <!-- ── CTA Content Orchestrator ── --> | |
| <g class="c-amber"> | |
| <rect x="120" y="318" width="320" height="56" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="280" y="340" text-anchor="middle" dominant-baseline="central">CTA content orchestrator</text> | |
| <text class="ts" x="280" y="360" text-anchor="middle" dominant-baseline="central">Aggregates per-user personalization · exposes API</text> | |
| </g> | |
| <!-- Orchestrator → DynamoDB (left) --> | |
| <line x1="120" y1="346" x2="114" y2="346" class="arr" marker-end="url(#arrow)"/> | |
| <g class="c-blue"> | |
| <rect x="14" y="322" width="100" height="48" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="64" y="340" text-anchor="middle" dominant-baseline="central">DynamoDB</text> | |
| <text class="ts" x="64" y="358" text-anchor="middle" dominant-baseline="central">Personalization</text> | |
| </g> | |
| <!-- Orchestrator → Kafka (right, L-shaped dashed) --> | |
| <path d="M440 346 L580 346 L580 436" fill="none" stroke="#888" stroke-width="1" stroke-dasharray="5 3" marker-end="url(#arrow)"/> | |
| <text class="ts" x="496" y="338" text-anchor="middle">publishes</text> | |
| <!-- ── Kafka ── --> | |
| <g class="c-green"> | |
| <rect x="520" y="436" width="120" height="56" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="580" y="458" text-anchor="middle" dominant-baseline="central">Kafka</text> | |
| <text class="ts" x="580" y="476" text-anchor="middle" dominant-baseline="central">Event stream</text> | |
| </g> | |
| <!-- Kafka → Databricks --> | |
| <line x1="580" y1="492" x2="580" y2="546" class="arr" marker-end="url(#arrow)"/> | |
| <!-- ── Databricks ── --> | |
| <g class="c-green"> | |
| <rect x="510" y="546" width="140" height="56" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="580" y="568" text-anchor="middle" dominant-baseline="central">Databricks</text> | |
| <text class="ts" x="580" y="586" text-anchor="middle" dominant-baseline="central">Analytics & ML</text> | |
| </g> | |
| <!-- Orchestrator → Router loop back --> | |
| <path d="M420 330 L448 330 L448 238 L422 238" fill="none" stroke="#888" stroke-width="1" stroke-dasharray="5 3" marker-end="url(#arrow)"/> | |
| <text class="ts" x="452" y="290" text-anchor="start">via router</text> | |
| <!-- Fan-out label --> | |
| <text class="ts" x="220" y="410" text-anchor="middle">Synchronous HTTP/gRPC calls</text> | |
| <!-- Router fan-out lines --> | |
| <line x1="195" y1="372" x2="80" y2="460" class="arr" marker-end="url(#arrow)"/> | |
| <line x1="245" y1="372" x2="190" y2="460" class="arr" marker-end="url(#arrow)"/> | |
| <line x1="315" y1="372" x2="300" y2="460" class="arr" marker-end="url(#arrow)"/> | |
| <line x1="355" y1="372" x2="410" y2="460" class="arr" marker-end="url(#arrow)"/> | |
| <!-- ── Content Services ── --> | |
| <g class="c-coral"> | |
| <rect x="30" y="460" width="100" height="56" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="80" y="482" text-anchor="middle" dominant-baseline="central">Promotions</text> | |
| <text class="ts" x="80" y="500" text-anchor="middle" dominant-baseline="central">CTA content</text> | |
| </g> | |
| <g class="c-coral"> | |
| <rect x="140" y="460" width="100" height="56" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="190" y="482" text-anchor="middle" dominant-baseline="central">Recs</text> | |
| <text class="ts" x="190" y="500" text-anchor="middle" dominant-baseline="central">CTA content</text> | |
| </g> | |
| <g class="c-coral"> | |
| <rect x="250" y="460" width="100" height="56" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="300" y="482" text-anchor="middle" dominant-baseline="central">Learning</text> | |
| <text class="ts" x="300" y="500" text-anchor="middle" dominant-baseline="central">CTA content</text> | |
| </g> | |
| <g class="c-coral"> | |
| <rect x="360" y="460" width="100" height="56" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="410" y="482" text-anchor="middle" dominant-baseline="central">Onboarding</text> | |
| <text class="ts" x="410" y="500" text-anchor="middle" dominant-baseline="central">CTA content</text> | |
| </g> | |
| <!-- Content services → personalization API --> | |
| <path d="M30 488 L16 488 L16 346 L14 346" fill="none" stroke="#888" stroke-width="1" stroke-dasharray="4 3" marker-end="url(#arrow)"/> | |
| <text class="ts" x="8" y="434" text-anchor="middle" transform="rotate(-90 8 434)">personalization API</text> | |
| <!-- Content services → data stores --> | |
| <line x1="80" y1="516" x2="80" y2="634" class="arr" marker-end="url(#arrow)"/> | |
| <line x1="190" y1="516" x2="190" y2="634" class="arr" marker-end="url(#arrow)"/> | |
| <line x1="300" y1="516" x2="300" y2="634" class="arr" marker-end="url(#arrow)"/> | |
| <line x1="410" y1="516" x2="410" y2="634" class="arr" marker-end="url(#arrow)"/> | |
| <!-- ── Data stores ── --> | |
| <g class="c-blue"> | |
| <rect x="28" y="634" width="104" height="48" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="80" y="652" text-anchor="middle" dominant-baseline="central">Postgres</text> | |
| <text class="ts" x="80" y="670" text-anchor="middle" dominant-baseline="central">Promotions DB</text> | |
| </g> | |
| <g class="c-blue"> | |
| <rect x="138" y="634" width="104" height="48" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="190" y="652" text-anchor="middle" dominant-baseline="central">DynamoDB</text> | |
| <text class="ts" x="190" y="670" text-anchor="middle" dominant-baseline="central">Recs DB</text> | |
| </g> | |
| <g class="c-blue"> | |
| <rect x="248" y="634" width="104" height="48" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="300" y="652" text-anchor="middle" dominant-baseline="central">Postgres</text> | |
| <text class="ts" x="300" y="670" text-anchor="middle" dominant-baseline="central">Learning DB</text> | |
| </g> | |
| <g class="c-blue"> | |
| <rect x="358" y="634" width="104" height="48" rx="8" stroke-width="0.5"/> | |
| <text class="th" x="410" y="652" text-anchor="middle" dominant-baseline="central">DynamoDB</text> | |
| <text class="ts" x="410" y="670" text-anchor="middle" dominant-baseline="central">Onboarding DB</text> | |
| </g> | |
| <!-- Legend --> | |
| <rect x="30" y="722" width="12" height="12" rx="2" fill="#F1EFE8" stroke="#5F5E5A"/> | |
| <text class="ts" x="48" y="733">Clients</text> | |
| <rect x="110" y="722" width="12" height="12" rx="2" fill="#E1F5EE" stroke="#0F6E56"/> | |
| <text class="ts" x="128" y="733">CTA orchestration</text> | |
| <rect x="258" y="722" width="12" height="12" rx="2" fill="#EEEDFE" stroke="#534AB7"/> | |
| <text class="ts" x="276" y="733">Gateway / routing</text> | |
| <rect x="398" y="722" width="12" height="12" rx="2" fill="#FAEEDA" stroke="#854F0B"/> | |
| <text class="ts" x="416" y="733">Orchestrator</text> | |
| <rect x="30" y="746" width="12" height="12" rx="2" fill="#EAF3DE" stroke="#3B6D11"/> | |
| <text class="ts" x="48" y="757">Kafka / Databricks</text> | |
| <rect x="178" y="746" width="12" height="12" rx="2" fill="#FAECE7" stroke="#993C1D"/> | |
| <text class="ts" x="196" y="757">Content services</text> | |
| <rect x="328" y="746" width="12" height="12" rx="2" fill="#E6F1FB" stroke="#185FA5"/> | |
| <text class="ts" x="346" y="757">Data stores</text> | |
| </svg> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment