Architecture · Deep dive · Runtime split
Static WordPress with Dynamic Runtime on AWS
A practical architecture for keeping WordPress pages static at the edge while selected interactions run through Cognito, API Gateway, Lambda, AI and workflow backends.
Architecture thesis: Static WordPress should not mean “no runtime.” It should mean the public page view is no longer coupled to PHP and MySQL. Runtime behavior becomes explicit: each login, form, AI request, protected file access or workflow call has its own API, authorization model, abuse controls and operational boundary.
The mistake: treating “static” as a feature ceiling
A static WordPress export is usually discussed as a performance and security move: render the site, publish files, serve them from a CDN, and remove the public PHP runtime. That is valuable, but it is only the first half of the architecture.
Real client sites still need runtime behavior. Visitors sign in. Forms submit. Chatbots answer. Private sections require access control. Editors need AI helpers. Agencies need repeatable deployment. None of those requirements disappear because the HTML is static.
The better question is not whether a static WordPress site can be dynamic. It is where each dynamic responsibility should live once WordPress is no longer the public request handler.
System boundary
Editors and administrators
│
▼
WordPress source site
content, CPTs, Gutenberg blocks, plugin settings
│
▼
Static Publisher export and deploy
│
▼
S3 + CloudFront public delivery
static pages, assets, cache, redirects, headers
│
▼
Browser-side WP Suite runtime
Gatey, AI-Kit, Flow blocks, custom components
│
├─ identity calls → Amazon Cognito
├─ protected static access → CloudFront signed-cookie issuer
├─ AI calls → AI-Kit backend on API Gateway + Lambda + Bedrock
├─ forms/workflows → Flow backend when enabled
└─ custom app calls → API Gateway + Lambda + DynamoDB/EventBridge
The public page request stays boring: CloudFront serves HTML and assets. Runtime starts only when the browser component reaches a boundary that needs identity, validation, model access, write operations or workflow execution.
Static Publisher is intentionally not a CloudFormation stack. It is the publishing and delivery tool. The stack-backed runtime pieces are the services around it: identity, protected delivery, AI backend, workflow backend and custom APIs.
Control plane versus runtime plane
The architecture becomes easier to reason about when WordPress is treated as a control plane instead of the universal runtime. WordPress still owns editorial intent: pages, blocks, URLs, schema, product settings, forms, chatbot placement and page composition. AWS owns the execution paths that should scale, isolate or secure independently.
| Responsibility | WordPress role | AWS/runtime role | Why this split matters |
|---|---|---|---|
| Content and layout | Editors build pages in Gutenberg and publish CPT content | Static delivery serves the rendered result | Editorial workflow remains familiar while public traffic avoids PHP. |
| Authentication UI | Page contains a Gatey block, shortcode or widget | Cognito handles sign-in, MFA, SSO and tokens | Login survives static export because it runs in the browser against Cognito. |
| Protected content | WordPress defines where protected sections live | CloudFront signed cookies enforce object access | Private static pages do not require WordPress sessions. |
| Forms and workflows | Form layout and workflow intent are edited in WordPress | Backend validates, stores, routes and triggers actions | Submission handling can scale separately from page delivery. |
| AI features | Blocks, chatbot placement, KB source selection and feature settings live in WP Admin | Model calls, RAG, guardrails and logging run in the AI backend | Content intelligence becomes a governed backend capability, not a PHP proxy. |
| Custom app features | WordPress renders buttons, containers and account-aware UI | API Gateway and Lambda enforce authorization and write state | The frontend can be static while the application stays interactive. |
Runtime capability map
Identity runtime
Gatey + Cognito
Handles sign-in, sign-up, MFA, SSO, profile state, JWTs and optional IAM credentials without relying on a WordPress session cookie.
Protected static runtime
CloudFront signed-cookie issuer
Converts accepted identity into a time-limited CloudFront access grant for private static paths while keeping S3 objects behind CloudFront.
AI runtime
AI-Kit backend
Exposes prompt, rewrite, summarize, translate, proofread, DocSearch and chatbot routes through API Gateway and Lambda, backed by Bedrock and optional Knowledge Base retrieval.
Workflow runtime
Flow backend
Receives public form submissions, draft saves, upload-url requests and admin workflow operations through the Flow backend API. The CloudFormation stack separates frontend routes from admin routes and backs them with Lambda, DynamoDB, S3, EventBridge, SES, WAF and optional reCAPTCHA.
Custom API runtime
API Gateway + Lambda
Runs feature-specific actions such as account operations, personalized lookups, integration calls, write operations and automation triggers.
Abuse-control runtime
WAF, reCAPTCHA, throttling and validation
Protects public-facing endpoints that must be callable from browsers, especially when a static site cannot hide behind WordPress nonce flows.
Flow runtime boundary after the backend template
With the Flow backend template available, the runtime boundary is no longer just “forms call an API.” Public endpoints handle final submissions, draft create/update/load/delete, draft finalization and presigned upload URLs. Admin endpoints manage form definitions, submissions, templates, workflows and webhook endpoints.
| Surface | Example routes | Runtime responsibility | Why it belongs outside PHP |
|---|---|---|---|
| Frontend forms | /frontend/forms/{formId}/submit, /drafts, /upload-url | Validate visitor input, accept drafts, receive payload references and trigger downstream processing. | The browser can submit from a static page while the backend owns validation, abuse controls and durability. |
| Admin operations | /admin/forms, /admin/submissions, /admin/templates, /admin/workflows, /admin/webhook-endpoints | Let WP Admin configure definitions, templates and workflows through protected management routes. | Administrative write operations can require Cognito/IAM, scopes and IP restrictions independently of public page delivery. |
| Workflow execution | EventBridge-triggered dispatchers for submissions, status changes, email and webhooks | Process work asynchronously and record events without holding open a page request. | Forms become reliable workflows, not one fragile synchronous WordPress POST. |
This does not make every form complex. It simply gives complex forms a proper backend when they need drafts, uploads, emails, webhooks, audit events or controlled admin operations.
Choose the runtime mode per feature, not per site
The most useful mental model is component classification. A single page can contain static content, public AI widgets, authenticated API calls and backend-only automation. Do not classify the whole site as “static” or “dynamic.” Classify every runtime surface.
| Runtime surface | Typical auth mode | Example WP Suite component | Primary risk | Recommended boundary |
|---|---|---|---|---|
| Anonymous page view | None | Static Publisher output | Cache invalidation or stale assets | CloudFront behavior, headers and redirect rules. |
| Login/profile UI | Cognito public client | Gatey Authenticator and Account Attribute blocks | Misconfigured callback URLs or token assumptions | Cognito App Client, callback domain, token handling. |
| Protected static path | Cognito before cookie issuance | Static Site Guardian flow | Cookie scope, expiry, key rotation | CloudFront signed cookies and signer service. |
| Public form or AI call | NONE + reCAPTCHA/WAF or Cognito | AI-Kit frontend routes, Flow frontend form, draft and upload endpoints | Endpoint abuse and model/submission cost | Rate limits, validation, reCAPTCHA, WAF and quotas. |
| Member API call | Cognito JWT or IAM | Gatey-secured API access | Frontend visibility mistaken for authorization | API Gateway authorizer, scopes or IAM signatures. |
| Admin/backend operation | IAM or admin-only Cognito scopes | AI-Kit admin routes, KB operations | Leaking privileged operations to public users | Separate /admin route, stricter auth, IP allow list. |
The browser component contract
A static page cannot depend on WordPress PHP at request time, so every interactive block needs a clear browser contract. This is where many static-plus-runtime projects become fragile: the HTML exports correctly, but a dynamically imported script, API URL, callback route or CORS rule is missing in the published environment.
Contract 1
All required assets are exportable
Blocks that dynamically import JavaScript chunks must use stable, published asset URLs so the static site can load the same runtime that the editor preview used.
Contract 2
Configuration is frontend-safe
The browser may know API URLs, user pool IDs, app client IDs and feature flags. It must not need server secrets, private keys or backend-only credentials.
Contract 3
Every write crosses an API boundary
Submissions, prompts, profile changes and protected data requests should be validated by an API or managed service, never by hidden fields or CSS state alone.
API and cache design
The runtime split creates a second architecture layer that many WordPress teams are not used to designing: API behavior now coexists with CDN behavior. A page can be cacheable for a year while a small widget inside it calls a non-cacheable API. That is a strength, but only if the boundary is explicit.
| Design area | Good pattern | Bad pattern | Why it matters |
|---|---|---|---|
| Static HTML caching | Long-lived cache with deterministic invalidation after publish | Short cache everywhere because one component is dynamic | One dynamic widget should not force the whole page back into server mode. |
| API routes | Separate /frontend and /admin surfaces with different auth and throttling | One generic endpoint that does every action | Public widgets and privileged operations have different risk profiles. |
| CORS | Allow the exact static domains and environments that need browser access | Wildcard CORS plus credentialed requests | Static sites often have multiple hostnames; CORS must be deliberate. |
| Stateful widgets | Store session state in Cognito, DynamoDB, S3 temp objects or purpose-built backend state | Assume WordPress session state exists after export | The exported page has no PHP session on public requests. |
| Error handling | Components show actionable “auth required,” “try again,” or “not available” states | Static page silently fails when an API is blocked | The frontend becomes the user-visible runtime boundary. |
Deployment pattern with CloudFormation-backed capabilities
The Deployment Wizard should not feel like a generic AWS console wrapper. Its job is to convert product intent into repeatable stack parameters: “I need Cognito login,” “I need protected static paths,” “I need AI fallback and RAG,” or “I need a workflow backend.”
1. Build the editorial surface in WordPress
│
▼
2. Classify runtime needs per component
│
├─ login / SSO → Cognito identity stack
├─ protected static paths → signed-cookie protection stack
├─ chatbot / DocSearch / AI fallback → AI-Kit backend stack
├─ forms / workflow submission → Flow backend stack
└─ custom feature → project-specific API stack
│
▼
3. Deploy selected stacks with explicit parameters
│
▼
4. Copy stack outputs into WP Suite plugin settings
│
▼
5. Export and publish static pages
│
▼
6. Test browser runtime against production domains
The outputs are as important as the resources. API base URLs, Cognito IDs, app client IDs, identity pool IDs, role ARNs, protected path settings and knowledge-base IDs become the contract between AWS and the WordPress admin experience.
Operational failure modes worth designing for
Missing dependencies
The page exports, but the widget breaks
Usually caused by missing JS chunks, wrong public path, CORS, stale plugin config or a feature that depended on WP Admin-only data. Test exported pages as anonymous users and signed-in users.
Unprotected API endpoints
Authorization is only visual
Showing or hiding a button is not backend security. Protected actions must enforce Cognito scopes, IAM signatures, signed cookies or server-side validation at the service boundary.
Unmonitored API and AI spend
Costs move from servers to calls
Static delivery reduces always-on capacity, but AI calls, API requests, logs and ingestion jobs become usage-sensitive. Add quotas, throttling and observability from the first deployment.
Tangled configurations
Environments drift
Development, staging and production may have different domains, callback URLs, reCAPTCHA keys, WAF rules and stack outputs. Treat environment configuration as part of the release.
When this pattern is worth it
- The site has mostly public content, but a few important interactive capabilities.
- You want static/CDN economics for page views without giving up login, AI, forms or APIs.
- Runtime load is bursty, unpredictable or different per feature.
- Security boundaries need to survive static export and cannot depend on WordPress sessions.
- Agencies need a repeatable model they can deploy across many client accounts.
When not to use it
- Every page is deeply personalized on the server before render.
- The team is not ready to own API security, logs, throttling and deployment parameters.
- A traditional dynamic WordPress plugin already solves the problem cleanly and the traffic/cost/security profile does not justify separation.
- The project cannot define stable frontend domains, callback URLs and runtime API endpoints.
Related architecture articles
Pillar
WordPress on AWS Reference Architecture
The hub article for how WP Suite splits content, delivery, identity, AI, APIs and workflows across WordPress and AWS.
Identity
Cognito Day-2 Identity Architecture
The identity backbone for sign-in, SSO, groups, custom emails, token scopes and IAM-backed API access.
AI backend
Private AI and RAG Backend Architecture
The deep dive into AI-Kit backend routes, Bedrock, Knowledge Base ingestion, grounding, guardrails and frontend/admin endpoint separation.
FAQ
Is this the same as headless WordPress?
No. Headless WordPress usually replaces the frontend rendering layer. This pattern keeps WordPress/Gutenberg as the page-building layer and publishes the rendered result, then adds runtime services where the static page needs interaction.
Does a static WordPress site still need APIs?
Only when the visitor experience includes runtime behavior such as login, forms, AI, protected data, profile actions or workflow triggers. Pure content pages can remain fully static.
Why not keep all dynamic behavior in WordPress AJAX?
That can be fine for a traditional dynamic WordPress site. After static export, public users no longer hit WordPress PHP for page views, so runtime actions need browser-reachable APIs or managed services outside the public WordPress runtime.
Can runtime services still be protected on a static frontend?
Yes. Depending on the feature, protection can use Cognito JWT scopes, IAM-signed requests, CloudFront signed cookies, WAF rules, reCAPTCHA, IP allow lists and backend validation. The important rule is that security must be enforced by the service boundary, not by the static page alone.
Where does Flow fit?
Flow belongs to the workflow runtime family: forms can be rendered by WordPress/static pages, while submissions, drafts, uploads, emails, webhooks and workflow events run through the Flow backend stack. The detailed implementation belongs in the Flow architecture article.
Keep the page static. Make the runtime explicit.
Use WordPress for editorial control, Static Publisher for delivery, and AWS-backed services for the interactions that genuinely need runtime behavior.
