The Problem That Wouldn't Go Away
It was 2 AM on a Tuesday, and I was staring at my browser's network tab again. The numbers were brutal:
TTFB: 847ms
For the third client project in a row, I was hitting the same wall. The headless WordPress site looked beautiful—modern React frontend, slick animations, perfect design. But the performance? Unacceptable.
"Just use WPGraphQL," everyone said. "It's the standard for headless WordPress."
So we did. And it was killing our Core Web Vitals.
This is the story of why we built Headless Bridge, and why WPGraphQL's approach to headless WordPress APIs is fundamentally flawed for most use cases.
The WPGraphQL Promise (and Reality)
When WPGraphQL launched, it was revolutionary. Finally, a proper GraphQL API for WordPress! No more wrestling with the clunky REST API. You could query exactly what you needed, nest relationships, and build truly decoupled WordPress sites.
The promise was incredible:
- Query flexibility with GraphQL
- Fetch only the data you need
- Reduce over-fetching and under-fetching
- Modern API for modern frameworks
But the reality was different:
// A simple query to get 10 blog posts
query {
posts(first: 10) {
edges {
node {
id
title
excerpt
featuredImage {
node {
sourceUrl
mediaDetails {
width
height
}
}
}
author {
node {
name
}
}
categories {
edges {
node {
name
}
}
}
}
}
}
}
This "simple" query to fetch 10 blog posts would trigger:
- 12+ database queries
- 500-800ms TTFB on a decent server
- 15KB+ response size with deeply nested JSON
- Performance degradation as content grows
And this was on a good day.
The Day Everything Broke
The turning point came with a high-traffic client project. A content publisher with 50,000+ posts and millions of monthly visitors.
Week 1: Everything seemed fine in development.
Week 2: Staging environment started showing cracks. API responses were hitting 1-2 seconds.
Week 3: Launch day. Within hours, the site was crawling. TTFB spiked to 3+ seconds during peak traffic.
Week 4: Emergency client meeting. "Why is our $50,000 headless WordPress site slower than our old WordPress theme?"
We tried everything:
- ✅ Enabled object caching (Redis)
- ✅ Added a CDN
- ✅ Optimized database queries
- ✅ Upgraded server resources (3x the cost)
- ✅ Implemented query complexity limits
- ✅ Added aggressive GraphQL query caching
Result: Marginal improvement. TTFB dropped from 3 seconds to 800ms. Still terrible.
The client threatened to cancel the project and revert to their old WordPress theme.
Understanding the Core Problem
After weeks of profiling, benchmarking, and digging through WPGraphQL's internals, I finally understood the fundamental issue:
WPGraphQL Computes Everything at Request Time
Every single API request goes through this process:
- Parse the GraphQL query (compute cost: ~10-20ms)
- Resolve field dependencies (compute cost: ~20-30ms)
- Execute multiple database queries (compute cost: ~50-300ms)
- Resolve nested relationships (compute cost: ~30-100ms)
- Format the nested response (compute cost: ~20-50ms)
- Return JSON to client (total: 130-500ms minimum)
Every. Single. Request.
Think about that. Your blog post content doesn't change between requests. Your featured images don't change. Your author names don't change. But WPGraphQL recomputes everything from scratch for every request, as if the data is constantly changing.
It's like going to a restaurant where the chef shops for ingredients, cooks your meal from scratch, and washes dishes after every single order—even though you ordered the same dish as the person before you.
The "Aha!" Moment
I was complaining about this to a friend over coffee when he asked a simple question:
"Why does the API need to compute anything at request time? Your content only changes when an editor hits 'Save', right?"
That's when it hit me.
Blog posts don't change at request time. They change at save time.
What if we pre-compiled the JSON response when content is saved, instead of computing it when requested?
- ✅ Database queries? Run once at save time.
- ✅ Field resolution? Run once at save time.
- ✅ JSON formatting? Run once at save time.
- ✅ API request? Return pre-compiled JSON. Done in <50ms.
This wasn't a new idea. Static site generators like Gatsby do this. But nobody was doing it inside WordPress for the API layer itself.
Building Headless Bridge
That weekend, I started prototyping.
The core concept was simple:
- When you save a post in WordPress, compile the full JSON response in the background
- Store it in the database as flat JSON
- When an API request comes in, return the pre-compiled JSON directly
- Zero computation. Zero nested queries. Zero runtime overhead.
The first benchmark results were shocking:
| Metric | WPGraphQL | Headless Bridge (v0.1) |
|---|---|---|
| TTFB | 487ms | 52ms |
| DB Queries | 12 | 1 |
| Response Size | 15.3KB | 8.1KB |
| Speed Improvement | Baseline | 9.4x faster |
Nearly 10x faster with just a prototype.
The Tradeoffs (And Why They Don't Matter)
Of course, there are tradeoffs. Nothing is free in software.
You Lose Query Flexibility
With WPGraphQL, you can query exactly what you want:
query {
posts {
title # Just the title
}
}
With Headless Bridge, you get a fixed JSON structure:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "My Blog Post",
"content": "...",
"excerpt": "...",
"featured_image": {...},
"author": {...},
"categories": [...]
}
But here's the thing: In practice, 95% of headless WordPress projects use the same standard queries:
- Get all posts
- Get single post
- Get posts by category
- Get posts by tag
- Get pages
You almost never need GraphQL's complex querying capabilities. And when you do, you're usually better off implementing that logic in your frontend or using a dedicated search service like Algolia.
Trade query flexibility for 10x performance? That's a deal most developers will take.
Content Updates Aren't Instant
With WPGraphQL, changes appear immediately in the API. With Headless Bridge, there's a small delay (typically 5-30 seconds) while content is recompiled in the background using WordPress's Action Scheduler.
But again: For 99% of content sites, instant updates don't matter. Blog posts, marketing sites, documentation—content changes a few times per day at most. A 10-second delay is totally acceptable in exchange for 10x faster performance.
If you need real-time updates (like a live sports site or stock ticker), Headless Bridge isn't for you. But most sites don't need that.
The Results
I rebuilt that failing client project using the Headless Bridge prototype.
Before (WPGraphQL):
- TTFB: 847ms average, 3000ms+ at peak
- Lighthouse Performance Score: 67
- Server costs: $400/month (upgraded resources to handle load)
- Client satisfaction: 3/10 (threatening to cancel)
After (Headless Bridge):
- TTFB: 58ms average, 95ms at peak
- Lighthouse Performance Score: 98
- Server costs: $120/month (downgraded back to original resources)
- Client satisfaction: 10/10 (gave us a testimonial and referred 2 new clients)
The client's exact words: "I don't know what you did, but this is exactly what I wanted from headless WordPress in the first place."
Making It Production-Ready
That prototype worked, but it wasn't production-ready. Over the next few months, we added:
Essential Features
- Background processing using Action Scheduler (no blocking saves)
- API key authentication for security
- Rate limiting to prevent abuse
- SEO metadata integration (Yoast, RankMath)
- Image optimization with srcset
- Multi-language support (WPML, Polylang)
- UUID-based IDs (no sequential ID leakage)
Advanced Features (Pro)
- ACF integration for custom fields
- Webhooks to trigger deploys on Netlify/Vercel
- Priority support
- Automatic updates
Performance Optimizations
- Indexed database queries for sub-50ms response times
- Flat JSON structure (no nested arrays to parse)
- Minimal payload size
- Database-level caching
The Benchmark Data
We ran comprehensive benchmarks against WPGraphQL, REST API, and Headless Bridge across different scenarios:
Scenario 1: Small Site (100 posts)
| API | TTFB | DB Queries | Response Size |
|---|---|---|---|
| WordPress REST API | 245ms | 8 | 12KB |
| WPGraphQL | 387ms | 12 | 15KB |
| Headless Bridge | 48ms | 1 | 8KB |
Scenario 2: Medium Site (10,000 posts)
| API | TTFB | DB Queries | Response Size |
|---|---|---|---|
| WordPress REST API | 512ms | 9 | 12KB |
| WPGraphQL | 847ms | 14 | 16KB |
| Headless Bridge | 51ms | 1 | 8KB |
Scenario 3: Large Site (100,000 posts)
| API | TTFB | DB Queries | Response Size |
|---|---|---|---|
| WordPress REST API | 1,240ms | 11 | 13KB |
| WPGraphQL | 2,150ms | 18 | 17KB |
| Headless Bridge | 53ms | 1 | 8KB |
The key insight: Headless Bridge performance stays flat regardless of content volume. WPGraphQL and REST API degrade significantly.
When You Should (and Shouldn't) Use Headless Bridge
✅ Perfect For:
Content-focused sites - Blogs, marketing sites, documentation, portfolios
- Content changes occasionally
- Performance is critical
- You use Next.js, React, Vue, or similar frameworks
High-traffic sites - News sites, magazines, publishers
- Millions of requests per month
- TTFB matters for SEO
- Server costs matter
Agency projects - Client sites with standard requirements
- Need ACF integration
- Want automated deploy webhooks
- Client expects fast sites
❌ Not Ideal For:
Real-time applications - Live sports scores, stock tickers, chat apps
- Content changes every second
- Need instant API updates
Complex data relationships - E-commerce with complex filters
- Need dynamic querying capabilities
- Require GraphQL's flexibility
Directory sites - Listings with thousands of search combinations
- Better served by Algolia or ElasticSearch
The Free vs Pro Decision
We decided to make Headless Bridge free and open source with optional Pro features.
Why free?
- We wanted to solve the WPGraphQL performance problem for everyone
- The core technology (pre-compilation) should be accessible
- Community adoption matters more than short-term revenue
Why Pro?
- Advanced features (ACF, webhooks) require ongoing maintenance
- Priority support costs money
- Sustainable development needs revenue
The split:
- Free: All core performance features, unlimited API requests
- Pro ($49.99/year): ACF, webhooks, priority support, auto-updates
- Agency ($299/year): Unlimited sites, white-label, dedicated support
99% of personal projects can use the free version. Professional projects that need ACF or webhooks upgrade to Pro. Agencies with multiple clients get Agency licenses.
What We Learned
Building Headless Bridge taught us several lessons:
1. Question "Best Practices"
Just because WPGraphQL is the "standard" doesn't mean it's the best solution. Sometimes the best approach is to go back to first principles and rethink the problem.
2. Performance Matters More Than Flexibility
Developers love flexible tools. But users don't care about GraphQL. They care about fast websites. Trade flexibility for performance every time.
3. Pre-compilation > Runtime Computation
For content that doesn't change often, pre-compilation is almost always faster than runtime computation. This applies beyond WordPress APIs.
4. Flat is Better Than Nested
Nested JSON structures are elegant in theory but painful in practice. Flat structures are easier to work with, smaller in size, and faster to parse.
Try It Yourself
Headless Bridge is available now:
- Free version: Download from WordPress.org
- Documentation: docs.headless-bridge.com
- Pro features: headless-bridge.com/pricing
Install it, run a benchmark against your current WPGraphQL setup, and see the difference for yourself.
What's Next?
We're actively developing new features:
Coming Soon:
- Menu endpoint for navigation
- Global options API for site-wide settings
- Search integration for Algolia/Meilisearch
- WooCommerce support (experimental)
On the Roadmap:
- Custom post type flexibility
- Multi-site support
- CDN integration (Cloudflare, Fastly)
- Analytics dashboard
Want to contribute? Open a GitHub issue or PR. We're building this in public.
Final Thoughts
WPGraphQL is an impressive piece of engineering. For applications that need GraphQL's query flexibility, it's still a solid choice.
But for the vast majority of headless WordPress projects—blogs, marketing sites, documentation, portfolios—you don't need GraphQL's complexity. You need speed.
That's why we built Headless Bridge.
If you're frustrated with slow TTFB, degrading performance at scale, or server costs that keep climbing, give Headless Bridge a try. It might just save your project—like it saved ours.
Ready to 10x your headless WordPress API?
Download Headless Bridge Free →
Questions? Comments? Find me on Twitter @HBridgeWP or email support@headless-bridge.com
About the Author
Andy Ryan is a full-stack developer who specializes in headless WordPress and modern JavaScript frameworks. After years of frustration with WPGraphQL performance, he built Headless Bridge to solve the speed problem once and for all. When not coding, you can find him enjoying nature while rock climbing and hiking.
Related Articles:
Top comments (0)