Zum Hauptinhalt springen
Sichere ProgrammierungI'm an AI agent. I read the agent-economy job boards' own numbers.(05.10.2026 um 03:41 Uhr)
••••
Sichere ProgrammierungYour ops dashboard does not need a frontend framework(05.10.2026 um 03:47 Uhr)
•
Sichere ProgrammierungThree pieces, zero readers: what I got wrong about publishing(05.10.2026 um 03:47 Uhr)
•
Sichere ProgrammierungProofDesk: A contact review is only as current as its evidence(05.10.2026 um 03:49 Uhr)
•
AI & KI NachrichtenAI Agents - Tool Calling And Its Types(05.10.2026 um 03:49 Uhr)
•
Sichere ProgrammierungSTAGE LADDER - A Private, Offline Speaking Coach Built for a Friend(05.10.2026 um 03:51 Uhr)
••
Sichere ProgrammierungI'm an AI agent. I read the agent-economy job boards' own numbers.(05.10.2026 um 03:41 Uhr)
••••
Sichere ProgrammierungYour ops dashboard does not need a frontend framework(05.10.2026 um 03:47 Uhr)
•
Sichere ProgrammierungThree pieces, zero readers: what I got wrong about publishing(05.10.2026 um 03:47 Uhr)
•
Sichere ProgrammierungProofDesk: A contact review is only as current as its evidence(05.10.2026 um 03:49 Uhr)
•
AI & KI NachrichtenAI Agents - Tool Calling And Its Types(05.10.2026 um 03:49 Uhr)
•
Sichere ProgrammierungSTAGE LADDER - A Private, Offline Speaking Coach Built for a Friend(05.10.2026 um 03:51 Uhr)
••
Intelligence View
⚡ tsecurity.de Intelligence

Migrating a Production Platform from CDK to SST Without Downtime

The Context Restore Blue is a platform for coastal restoration projects. It helps organizations track solutions, manage projects, generate reports, and search…

Beitrag
0
Seite
0
↗ Quelle (dev.to)
Social ReaktionenReagiere als Erste:r — dein Feedback zählt!




The Context



Restore Blue is a platform for coastal restoration projects. It helps organizations track solutions, manage projects, generate reports, and search a knowledge base of restoration techniques. The original stack used AWS CDK v2 with ten separate stacks, a DocumentDB database, and a separate chat bot repository for AI search with OpenSearch Serverless.



The team decided to migrate to SST v4. The reasons were practical. SST gives you one config file instead of ten stacks, live Lambda development, and a simpler mental model for infrastructure. But the migration touched every layer of the system and the platform had active users.



This article walks through the architecture decisions we made as a team, what worked, what did not, and what we would do differently next time.









The Gap Between Old and New



The legacy system and the target system differed in almost every dimension.


























































Layer Legacy Target
Infrastructure AWS CDK v2, 10 stacks SST v4, one config
Database DocumentDB (MongoDB) Aurora Serverless v2 (PostgreSQL)
Query layer Custom in-house ORM Kysely (type-safe)
AI search Separate repo, OpenSearch Serverless pgvector on the same Postgres instance
Frontend UI Bespoke components shadcn-svelte design system
API client Raw fetch calls Typed client with shared types
D3 charts Full d3 bundle with DOM manipulation Specific sub packages only
CI/CD Custom Node build scripts AWS CodePipeline with versioned tooling
ID strategy MongoDB ObjectIDs UUID v4 with legacy ID tracking


None of these decisions were made in isolation. A senior solutions architect guided the database schema design. A cloud engineer handled the VPC and networking setup. Different team members owned different parts of the frontend, the API layer, and the migration tooling. What made it work was the shared understanding of what we were building toward.









Database Migration: DocumentDB to PostgreSQL



The hardest part of any migration is the data. We were moving from MongoDB to Postgres, which is not just a driver swap. It is a different data model, different query patterns, different indexing strategy.



The legacy DocumentDB instance used a custom in house ORM layer that wrapped MongoDB queries. We replaced it with Kysely, a TypeScript native query builder that generates typed SQL. This gave us compile time query validation instead of runtime field name errors.



The schema design went through an audit first. We profiled every collection in the legacy database and found twelve active lookup tables that we kept, plus six that had zero population or no handler reads and were dropped. One collection labeled "species" turned out to be target group data. That was corrected during the design phase.



For the migration itself, we wrote a phased migration plan with eight phases. Each phase had gates, deliverables, and verification steps. The plan covered schema creation, data migration, API route porting, frontend rework, and cutover.



The senior architect designed the table structure with code based lookups, soft deletes on every table, and an append only status log pattern for entities that change state over time. That design scaled well and we have not needed to restructure any tables since going live.









The AI Search Pivot



The legacy system used a separate repository for AI search. It ran Bedrock Knowledge Base with OpenSearch Serverless as the vector store. Two separate services, two separate deploy pipelines, two sets of infrastructure to maintain.



OpenSearch Serverless has a pricing model based on OpenSearch Compute Units (OCUs). There is a minimum floor that makes it expensive for workloads with intermittent traffic. We decided to move the vector search into the main Postgres database using pgvector.



The team built a hybrid retrieval system. pgvector handles cosine similarity for semantic search, and PostgreSQL's built in tsvector handles BM25 keyword ranking. The results are merged using Reciprocal Rank Fusion, which combines the two ranked lists into a single score.



The embedding model stayed on Bedrock Titan v2. The generation model switched from Claude Haiku to Nova Lite. This was not a performance choice. It was an AWS account constraint. Fresh accounts have a gated Marketplace subscription for certain Bedrock models, and we could not get access in time for the migration deadline.



This taught us something about architecture: the best AI stack is the one your AWS account lets you use. Plan for subscription gates early.









Frontend: From Bespoke to Design System



The legacy frontend was built component by component with no shared design system. Every page had its own buttons, its own modals, its own table styles. The code worked but it was inconsistent and slow to build new features.



The team adopted shadcn-svelte as the UI foundation. This gave us 37 hand built primitives including buttons, inputs, selects, comboboxes, tabs, dialogs, sheets, toasts, tables, and pagination. Every component uses the same Tailwind theme with 11 step OKLCH color scales.



One person on the team owned the Mapbox integration for the global research tracking page. The legacy version used the default Mapbox style and had a functional but basic marker implementation. The target version moved to the light v11 style explicitly, added proper accessibility with ARIA labels and focus visible states, and showed a warning alert when the token was missing. The component also code splits the Mapbox import using dynamic await import(), which keeps the initial bundle smaller.



Another team member rebuilt the D3 donut chart. The legacy version used the full d3 package with d3-selection for direct DOM manipulation and d3-interpolate for animations. The target version uses only d3-array, d3-scale, and d3-shape. No DOM manipulation. No animation library. Instead of creating SVG elements imperatively, the chart renders using Svelte's {#each} blocks and updates reactively through $derived signals.



The animation was removed. It looked nice but it added complexity and a dependency that was only used by one chart. The team decided that correctness and maintainability mattered more than the entrance transition.









The API Client Decision



When we built the typed API client, we evaluated three approaches.



tRPC was the first candidate. It gives you end to end type safety with zero boilerplate. But we were building a REST API with Cognito authentication, not a procedure call architecture. Forcing tRPC into a REST shape felt wrong.



openapi-typescript would have generated types from an OpenAPI spec. But we did not have a spec. Writing one just for the codegen added a maintenance burden with no clear benefit.



Hand written wrappers won. Each API domain gets its own typed namespace in the frontend, backed by shared types from the core package. The types are consumed from @sst-restore-blue/core/api-types, which is a types only barrel that cannot import any backend modules.



A CI script checks for bundle leakage. If a backend module like pg or kysely somehow makes it into the client bundle, the script fails the build. This gave us confidence that the shared types approach would not accidentally ship server code to the browser.



It is not the most elegant solution, but it works reliably. Rename a backend type and the frontend stops compiling. No runtime errors, no mismatched interfaces, no manual synchronization.









What We Would Do Differently



Centralized admin lookups caused problems. We initially loaded all lookup tables in the admin layout using Promise.all with thirteen parallel requests. In SST's live development mode, each request hits the authorizer Lambda which cold starts in 18 seconds or more. Thirteen parallel cold starts pushed every request past API Gateway's 30 second timeout. We reverted to per page narrow loads.



Streaming was worth the effort. Sixteen routes use SvelteKit's streaming server loads. The page chrome paints immediately while data streams in as Result envelopes. The perceived performance improvement was noticeable even before we optimized the actual query times.



The bundle leakage check should have been built from day one. We added it mid migration after discovering that a route file was importing a database client directly. The error would have reached production if we had not caught it.









Summary



Migrating from CDK to SST was not just a framework upgrade. It was an opportunity to rethink every layer of the stack. The database, the search infrastructure, the frontend design system, the API client architecture, and the CI/CD pipeline all changed.



The senior architect designed the schema. The cloud engineer handled the infrastructure. Different team members owned different parts of the frontend and backend. The Mapbox integration, the D3 rebuild, the API client, the AI search refactor, the admin lookup rework, each piece was built by someone different but fit into a shared understanding of the system architecture.



That is the part that matters more than any single technology choice. A team that communicates well will build a better system than a team of brilliant individuals who do not.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Migrating a Production Platform from CDK to SST Without Downtime

Thematisch verwandte Begriffe: Migrating, Production, Platform, from · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
Nächster Beitrag