Building a Modern eCommerce Platform with Optimizely PaaS and Next.js SaaS Frontend: Part 1 – Architecture Overview
Introduction
When you're building a modern eCommerce experience, it's tempting to reach for familiar tools. But monoliths break down fast under real-world load—especially when content teams and developers are moving at different speeds.
We wanted something better.
So we built a platform that combines Optimizely’s enterprise-grade CMS and commerce engine with a custom SaaS frontend in Next.js—fast, scalable, and actually enjoyable to work on.
This post walks through the architecture behind the platform—how we decoupled the backend and frontend, connected the pieces effectively, and ensured the system could scale without sacrificing developer speed.
The Challenge
We needed a system that could handle high traffic, support complex business workflows, and make life easier for both developers and content editors. We also wanted speed—both in the frontend experience and in our release cycle. Infrastructure had to be managed. Deployments had to be automated. Content sync needed to be real-time and reliable.
Traditional approaches often force you to choose between a full-featured CMS and a modern frontend framework. We wanted both, and we didn’t want to duct-tape them together.
Why Optimizely PaaS + Next.js Frontend?
On the backend, we chose Optimizely’s Digital Experience Platform (DXP) for a few key reasons: mature CMS and commerce capabilities, managed infrastructure, and a built-in GraphQL API via Content Graph. It let us offload hosting, focus on business logic, and give content teams the editorial tools they needed.
On the frontend, we went all-in on a standalone app built in Next.js 14. That gave us full control over routing, rendering, and performance, with support for server components and static generation. It also let us scale and deploy independently from the backend, which became critical as the app grew.
Architecture Overview
This is a true headless eCommerce architecture. The CMS and commerce system power the experience, while our frontend app consumes content via GraphQL and exposes its own APIs for auth, business logic, and third-party integrations.
graph LR subgraph "Presentation Layer" FE[Next.js Frontend] CDN[Cloudflare CDN] end subgraph "API Gateway Layer" CG[Content GraphGraphQL] REST[Custom REST APIs] end subgraph "Application Layer" CMS[Optimizely CMS 12] COMM[Optimizely Commerce 14] end subgraph "Data Layer" DB[(Databases)] STORAGE[Blob Storage] end subgraph "External Services" OKTA[Okta] PAY[Payment] EMAIL[Email] end FE --> CG FE --> REST CDN --> CMS CG --> CMS CG --> COMM REST --> CMS REST --> COMM CMS --> DB COMM --> DB CMS --> STORAGE COMM --> STORAGE REST --> OKTA REST --> PAY REST --> EMAIL style FE fill:#61dafb style CMS fill:#ff6b35 style COMM fill:#ff6b35 style CG fill:#8e44ad style REST fill:#e74c3c
Detailed System Architecture
1. Optimizely PaaS Backend
We use Optimizely CMS 12 and Commerce 14 as the backbone of our content and commerce logic. Editors manage flexible content types, blocks, page templates, and multilingual content in a familiar UI. On the commerce side, the system handles catalogs, pricing, and order workflows out of the box.
Content is served through Optimizely Content Graph (GraphQL) and we expose additional functionality through custom ASP.NET Core REST APIs.
The data layer is split into two SQL databases (CMS and Commerce), backed by Azure Blob Storage for media and distributed session storage for auth state and caching. Hangfire handles background jobs like content indexing and async workflows, with queues for transactional tasks (emails, reporting, integrations).
Okta handles authentication and single sign-on, with JWT/OAuth for secure API access. All sensitive config is encrypted using .NET’s built-in data protection stack.
2. Next.js Frontend
The frontend is a standalone SaaS app running on Next.js 14 with the App Router. Routes are split between server and client components, letting us deliver fast pages with dynamic interactivity where it counts.
We treat the frontend as its own product, with independent deployment, CI/CD, observability, and scaling strategy. URQL powers our GraphQL integration with fully typed queries. API routes handle custom logic and third-party calls.
State management is layered: React Context for global app state, hooks for local UI state, and React Hook Form for user input. Content updates trigger via webhooks and invalidate the right cache layer automatically.
Images are optimized on the fly using Next.js + Cloudflare, and static generation (plus ISR) handles our most traffic-heavy pages. The result: near-instant page loads and a strong SEO foundation.
3. Integration Layer
The glue layer matters.
We built a tight integration between the CMS and frontend via webhooks, custom GraphQL schema resolvers, and draft/preview support. Content updates propagate in near real-time. We also built integrations for payments, transactional email, analytics, and user sessions—all routed through our custom API layer with error handling and retries built in.
SSO and auth span the stack using secure tokens and consistent role-based access control. Permissions map directly to what users see in the UI.
4. Infrastructure & DevOps
The backend is hosted in Optimizely DXP. The frontend runs on Azure App Service in containers. Each scales independently.
We use geo-replicated Azure SQL, Azure Blob Storage with lifecycle policies, and separate CI/CD pipelines (Azure DevOps for backend, GitHub Actions for frontend). Environments are consistent across dev, QA, pre-prod, and prod.
Deployments are blue-green with rollback support. Observability is built in with Application Insights, Serilog, structured logs, and health checks. We get alerts for the stuff that matters—long-running jobs, failed requests, and memory bottlenecks.
Tech Stack
Backend
- Framework: .NET 8 / ASP.NET Core
- CMS & Commerce: Optimizely CMS 12.32.4 / Commerce 14.34.0
- Database: SQL Server 2019+ (EF Core 9)
- Jobs: Hangfire 1.8.18
- Auth: Okta.AspNetCore 4.6.2 (OIDC)
- Storage: Azure.Storage.Blobs 12.24.0
- Monitoring: Serilog.AspNetCore 9.0.0 + Application Insights
- Docs: Swashbuckle.AspNetCore 7.1.0
Frontend
- Framework: Next.js 14.2.28 (App Router)
- Language: TypeScript 5.7.2
- UI: React 18.3.1 + Server Components
- Styling: Tailwind CSS 3.4.17
- State: React Hooks + Context API
- GraphQL: URQL 4.2.1 + Optimizely Graph
- Build Tool: Vite 6.2.0
- Docs: Storybook 9.0.8
- Forms: React Hook Form 7.54.2
- Animations: Framer Motion 11.12.0
DevOps
- CI/CD: Azure DevOps (backend) + GitHub Actions (frontend)
- Hosting: Azure App Service + Optimizely DXP
- CDN: Cloudflare (w/ custom image loader)
- Monitoring: App Insights + structured telemetry
- Version Control: Git w/ conventional commits
- Package Mgmt: NuGet (backend) + Yarn 4.6.0 (frontend)
Benefits of This Architecture
This approach isn’t just modern for the sake of modern. It solves real problems in headless eCommerce platform delivery.
🔹 Scalability Without the Drama
- Backend and frontend scale independently
- The cloud handles SQL and storage
- Auto-scaling policies respond to traffic in real time
⚡ Performance Where It Matters
- SSR and SSG deliver fast loads
- GraphQL avoids over-fetching
- Cloudflare optimizes images on the fly
- Multi-layer caching keeps everything snappy
🛠️ Developer Experience That Doesn’t Suck
- Modern frameworks, full TypeScript coverage
- Component-driven architecture, fast feedback loops
- Storybook, hot reload, and clean CI pipelines
📝 Content That Works for Editors
- Workflows, localization, previews
- Immediate updates via webhooks
- Confident publishing without dev bottlenecks
🔧 Maintenance That’s Actually Maintainable
- Managed infrastructure
- Isolated deployments
- Built-in monitoring and clean separation of concerns
Wrapping Up
This architecture wasn’t just about choosing the latest tools. We solved real-world constraints: getting content and code to move at the same pace, making authentication seamless across system boundaries, and scaling cleanly without reinventing deployment every time a feature shipped.
The result is a platform that works at scale, adapts to change, and delivers an experience developers want to build on and editors actually want to use.
In Part 2, I’ll dive into the frontend implementation: how we structured our App Router-based Next.js app, wired up the GraphQL layer with full type safety, built our Storybook-driven component system, and optimized performance at every layer—from data fetching to image delivery.
If you’re building a headless site with real content workflows and real dev velocity requirements, this is where the rubber meets the road.
Stay tuned.