Jay's Tech Bites Logo

Why JAMstack Teams Are Quietly Moving to Composable Architecture

Static sites were revolutionary. Then we asked them to do too much.

JAMstack solved yesterday's problems brilliantly. I've watched it break under today's requirements. Here's what teams are actually building instead.

Jay McBride

Jay McBride

Software Engineer

7 min read
Support my work on Buy Me a Coffee

I spent three years building JAMstack sites. Fast, secure, simple to deploy. Then I watched every one of them hit the same wall: the client needed personalization. Or real-time updates. Or content that couldn’t wait for a 15-minute build.

JAMstack didn’t fail. We just asked it to solve problems it was never designed for.

The teams I work with now aren’t abandoning static sites—they’re abandoning the idea that static-first architecture scales to dynamic needs. They’re building composable systems instead. Not because it’s trendy, but because JAMstack’s constraints finally cost more than they saved.

JAMstack Worked Until It Didn’t

JAMstack was brilliant for its time. Pre-render everything, serve from CDN, decouple frontend from backend. Fast, secure, simple.

I built marketing sites, documentation, blogs. They were blazingly fast. Security was a non-issue. Deployments were trivial.

Then requirements changed:

“We need personalized content based on user behavior.” Client-side JavaScript could fake it, but real personalization meant hitting APIs after load. So much for pre-rendering.

“We need real-time inventory updates.” Build times were 10 minutes. Inventory changed every 30 seconds. Static generation was useless.

“We need to serve this content on web, mobile app, and in-store kiosks.” JAMstack’s HTML output worked great for web. Everything else required different architecture.

Every workaround made the system more complex. Eventually, we weren’t building JAMstack sites—we were building dynamic apps with vestigial static generation.

Where JAMstack Actually Breaks

Not theory. Actual production failures I’ve watched happen:

Build times that kill iteration speed. I’ve seen 30-minute builds for sites with 10,000 pages. Change one nav item? Rebuild everything. Wait half an hour. Hope you didn’t introduce a bug.

Client-side complexity that destroys performance. Moving logic to JavaScript looks clean until you’re shipping 500kb of bundle to render personalized content. You traded server complexity for client bloat.

Static generation that can’t handle dynamic content. Incremental Static Regeneration helped, but it’s still a hack. You’re trying to make static architecture solve dynamic problems.

Omnichannel delivery that doesn’t work. Pre-rendered HTML is great for browsers. Mobile apps need JSON. IoT devices need something else. Now you’re maintaining multiple output formats.

What Composable Architecture Actually Means

Forget the buzzwords. Composable architecture is what happens when you stop treating your entire system as one deployment unit.

Instead of a monolith (even a static one), you build Packaged Business Capabilities (PBCs). Each PBC:

  • Owns a specific domain (Search, Cart, Checkout, Content)
  • Exposes clean APIs and events
  • Can be swapped, upgraded, or replaced independently
  • Has its own team and deployment cycle

I’ve watched teams move from “rebuild the entire site” to “deploy the Cart service.” The productivity difference is massive.

Why This Matters More Than Performance

Everyone talks about composable architecture like it’s a scaling solution. That’s true, but it misses the bigger point.

The real benefit: iteration speed.

I’ve seen teams go from quarterly releases to weekly deployments. Not because the technology was faster, but because changing one component didn’t require rebuilding everything.

Your search functionality is broken? Deploy a fix to Search. Your checkout flow needs A/B testing? Update Checkout without touching Content.

This isn’t theoretical. I’ve watched a three-person team outship a fifteen-person team because the smaller team had composable architecture and the larger team had a monolithic JAMstack build.

The Migration Pattern That Actually Works

Every team I’ve worked with tried to migrate everything at once. Every one of them failed.

What works: Strangler Fig pattern.

Pick one capability. Extract it. Run both old and new in parallel. Gradually shift traffic. Once it works, move to the next.

First migration I usually see: Search.

  • Search is isolated enough to extract cleanly
  • It has clear inputs and outputs
  • It needs to be fast and dynamic anyway
  • Teams learn composable patterns without betting everything

Second migration: Catalog or Content.

  • More complex than Search
  • Tests whether your service boundaries make sense
  • Reveals integration pain points before they’re critical

Last migration: Checkout or User Management.

  • These are critical flows
  • You need confidence from earlier migrations
  • Failure here costs money

Most teams take 6-18 months to fully migrate. The ones who rush it create more problems than they solve.

What Teams Get Wrong About Composability

Mistake: Treating it like microservices. Microservices focus on technical decomposition. Composable architecture focuses on business capabilities. The difference matters.

Bad: “We’ll break the database layer into services.” Good: “We’ll build independent services for Search, Cart, and Checkout.”

Mistake: Over-engineering from day one. You don’t need event-driven architecture, API gateways, and service mesh on day one. Start simple. Add complexity when it solves actual problems.

Mistake: Vendor sprawl without governance. Composable means you can use best-of-breed services. But 47 different vendors means 47 different auth systems, billing models, and support contracts. Govern your stack.

Mistake: Ignoring frontend complexity. Breaking backend into services is half the battle. Your frontend still needs to orchestrate them. Islands Architecture and Server Components help, but they’re not automatic.

The Frontend Story: Beyond Static Site Generation

JAMstack’s frontend story was simple: generate HTML, serve it. Composable architecture complicates this.

Your page now pulls data from multiple services. How do you render that efficiently?

Islands Architecture (Astro, Fresh): Render most content server-side. Hydrate only interactive components. You get static performance with dynamic capabilities.

React Server Components: Blur the line between server and client. Render on server where it makes sense, client where it doesn’t. More complex than islands, more flexible.

Streaming SSR: Don’t wait for all data before rendering. Stream HTML as it becomes available. Users see content faster, even if backend services are slow.

These aren’t competing approaches—they’re tools for different tradeoffs. What matters is knowing when you need dynamic rendering and when static works fine.

The Integration Layer Everyone Ignores

Composable architecture means services need to communicate. Most teams underestimate this complexity.

API gateways handle authentication, rate limiting, request routing. Necessary, but they become a bottleneck if you’re not careful.

Backend-for-Frontend (BFF) patterns let you tailor API responses per client. Mobile gets different data than web. Kiosks get something else. This prevents over-fetching but adds architectural complexity.

Event-driven architecture decouples services. “OrderPlaced” events trigger inventory updates, email notifications, analytics. When it works, it’s beautiful. When events get lost or duplicated, debugging is hell.

I’ve watched teams spend months building integration layers they didn’t know they needed. Factor this into your timeline.

When JAMstack Still Makes Sense

Not everything needs composable architecture. Most things don’t.

JAMstack still wins for:

  • Marketing sites (mostly static, occasional updates)
  • Documentation (version-controlled, build-triggered updates work great)
  • Blogs (content changes infrequently, speed matters)

If your content is mostly static and you don’t need per-user personalization, JAMstack is still the right choice. The simplicity is a feature.

The mistake is trying to force JAMstack to solve problems it wasn’t designed for.

What This Migration Actually Costs

Composable architecture isn’t free. Here’s what teams underestimate:

Development complexity increases. You’re managing multiple services instead of one codebase. Local development gets harder. Debugging spans services.

Operational overhead increases. More services means more deployments, more monitoring, more things to break.

Team coordination becomes critical. When services depend on each other, teams need to coordinate changes. APIs become contracts that can’t casually break.

Cost often increases. JAMstack hosting is cheap. Managed services for search, content, commerce add up quickly.

For some teams, these costs are worth it. For others, they’re unnecessary complexity.

The Pattern I’m Seeing Work

The successful migrations I’ve watched share a pattern:

  1. Audit what’s actually dynamic. Most pages are static. Some components are dynamic. Know the difference.

  2. Extract one high-value capability. Search, product catalog, user-generated content—pick something that hurts in JAMstack.

  3. Build with clear API contracts. Your other services and your frontend need stable interfaces.

  4. Run hybrid architecture. Static pages stay static. Dynamic capabilities become services. Don’t force everything to match.

  5. Measure business impact. Are you shipping faster? Is the site more reliable? If not, you’re adding complexity without benefit.

Where This Actually Goes

Composable architecture isn’t the final answer. It’s the current answer to JAMstack’s limitations.

Five years from now, we’ll probably have different patterns. Edge computing might eliminate some service complexity. Better frameworks might make orchestration trivial.

What won’t change: the tension between simple architecture and complex requirements.

JAMstack optimized for simplicity. Composable architecture optimizes for flexibility. Both have costs.

The teams that succeed are the ones who understand what they’re optimizing for and what they’re giving up.

What You Should Actually Do

Don’t migrate to composable architecture because it’s trendy. Migrate when JAMstack’s constraints cost more than its benefits.

Start with JAMstack if:

  • Your content is mostly static
  • Build times are acceptable
  • You don’t need real-time updates
  • Simplicity matters more than flexibility

Move to composable when:

  • Build times kill your iteration speed
  • You need per-user personalization
  • Multiple channels need different outputs
  • Different teams need to ship independently

Understand the tradeoffs. Choose consciously. Don’t overcomplicate until complexity solves real problems.

Most teams should start simple. Some will outgrow it. That’s fine. Knowing when to evolve matters more than predicting it perfectly.

Found this helpful?

Share it with your network

Jay McBride

Written by Jay McBride

Software engineer with 10+ years building production systems and mentoring developers. I write about the tradeoffs nobody mentions, the decisions that break at scale, and what actually matters when you ship. If you've already seen the AI summaries, you're in the right place.

Based on 10+ years building production systems and mentoring developers.

Support my work on Buy Me a Coffee

Recommended for You

10 min read

Why I Stopped Defaulting to React for Every Project

After years of watching teams drown in JavaScript complexity, I'm back to building most apps with server-rendered frameworks—and shipping faster than ever.

Read Article
6 min read

Why Your Android-First Mobile Strategy Is Leaving Money on the Table

iOS users spend 2x more per app—here's what most founders get wrong about platform prioritization

Read Article