
Introduction
Ghost is known for being a fast, modern publishing platform, but speed in development does not automatically guarantee speed in production. If your Ghost CMS powers a high-traffic blog, membership site, newsletter archive, or content-driven e-commerce experience, you need to know how it behaves under real user load. A homepage that feels instant for one editor can slow down dramatically when thousands of readers hit featured posts, search pages, tag archives, and member-only content at the same time.
That is why Ghost load testing matters. With proper load testing, performance testing, and stress testing, you can benchmark how Ghost handles concurrent traffic, identify bottlenecks in your theme or infrastructure, and validate that publishing workflows and content delivery remain fast during traffic spikes. This is especially important for media launches, newsletter sends, seasonal campaigns, and viral content events.
In this guide, you will learn how to load test Ghost CMS with LoadForge using realistic Locust scripts. We will cover public content delivery, authenticated member flows, Ghost Admin API publishing actions, and more advanced scenarios that reflect how Ghost is actually used in production. Because LoadForge runs on cloud-based infrastructure with distributed testing, real-time reporting, CI/CD integration, and global test locations, it is well suited for benchmarking Ghost performance from multiple regions and at meaningful scale.
Prerequisites
Before you start load testing Ghost CMS, make sure you have the following:
- A running Ghost instance, such as:
https://your-ghost-site.comhttps://staging.your-ghost-site.com
- Access to the parts of Ghost you want to test:
- Public frontend pages
- Member login endpoints if memberships are enabled
- Ghost Content API or Admin API if relevant
- A staging or pre-production environment that closely matches production
- A valid Ghost Admin API key if you want to test publishing or admin workflows
- Optional member test accounts for authenticated user scenarios
- LoadForge account access to run distributed load testing at scale
You should also know which Ghost features are enabled on your site. For example:
- Native memberships and subscriptions
- Search integration
- Custom theme with heavy images or JavaScript
- Newsletter archive pages
- Dynamic routing with tags, authors, and collections
- External integrations like Stripe, CDN, or image optimization
For safe performance testing, avoid running destructive or high-volume write tests against production unless you fully understand the impact. Publishing, editing, or member management tests should usually run in staging.
Understanding Ghost Under Load
Ghost is built on Node.js and is generally efficient for content delivery, but several layers can influence performance under load.
How Ghost handles concurrent traffic
Most Ghost traffic is read-heavy. Typical requests include:
- Homepage requests
- Individual post pages
- Tag and author archive pages
- Asset requests for CSS, JavaScript, fonts, and images
- Member login and account access
- API requests from the frontend or integrations
Ghost can serve these efficiently, especially when combined with:
- Reverse proxies like Nginx
- CDN caching
- Optimized themes
- Database tuning
- Proper image sizing
Common Ghost bottlenecks
When load testing Ghost CMS, these are the most common bottlenecks to watch for:
Theme inefficiencies
A custom Ghost theme may generate excessive API calls, oversized images, render-blocking assets, or expensive dynamic components. Even if Ghost itself is fast, the theme can slow down page delivery.
Database pressure
Ghost relies on a database backend and can become slower if pages trigger expensive queries, especially on large sites with many posts, tags, members, or newsletter records.
Member authentication overhead
Sites using memberships often see added complexity from:
- Sign-in flows
- Session creation
- Member-only content checks
- Portal or account-related frontend scripts
Admin and publishing operations
Publishing content through the Ghost Admin API is usually less frequent than public traffic, but it matters for editorial teams. Bulk publishing, scheduled content, and media uploads can stress the application and storage stack.
Asset delivery and cache misses
If your CDN is misconfigured or disabled, Ghost may end up serving too many static resources directly. Load testing should help you distinguish between cached and uncached performance.
A good Ghost performance testing strategy should therefore include both anonymous reader traffic and targeted authenticated or admin workflows.
Writing Your First Load Test
The best first test for Ghost is a read-only traffic simulation that reflects real visitor behavior. This means hitting the homepage, a few post pages, and tag pages with realistic wait times.
Below is a basic Locust script for load testing a public Ghost site.
from locust import HttpUser, task, between
class GhostPublicUser(HttpUser):
wait_time = between(1, 5)
@task(5)
def homepage(self):
self.client.get("/", name="GET /")
@task(3)
def featured_post(self):
self.client.get("/welcome/", name="GET /welcome/")
@task(2)
def tag_page(self):
self.client.get("/tag/news/", name="GET /tag/news/")
@task(1)
def author_page(self):
self.client.get("/author/ghost/", name="GET /author/ghost/")What this script does
This script simulates anonymous readers browsing your Ghost site:
- The homepage is the most common request
- A single post page is frequently visited
- Tag archives are loaded less often
- Author pages are visited occasionally
The weighted @task decorators approximate realistic traffic distribution. This is much better than hammering a single URL because it reflects how Ghost traffic is usually spread across multiple content routes.
Why this is useful
This first load test helps answer basic questions:
- How many concurrent readers can Ghost handle?
- Does homepage latency increase under load?
- Are post pages slower than archive pages?
- Do any routes return errors under higher concurrency?
In LoadForge, you can run this script across multiple cloud regions to simulate geographically distributed readers. That is especially useful for content publishers with global audiences.
Making the test more realistic
For a real Ghost site, replace the sample paths with actual routes from your installation, such as:
//newsletter//tag/product-updates//author/editorial-team//2024/11/holiday-buying-guide/
You should also include enough unique content URLs to avoid unrealistic cache behavior. Testing only one post page may overstate performance if that page is heavily cached.
Advanced Load Testing Scenarios
Once you have a baseline, move on to more realistic Ghost performance testing scenarios. The following examples cover content API access, member login flows, and Ghost Admin API publishing.
Advanced Scenario 1: Testing Ghost Content API traffic
Many Ghost themes and headless implementations use the Content API to fetch posts, tags, and site data. If your frontend depends on these endpoints, you should load test them directly.
from locust import HttpUser, task, between
CONTENT_API_KEY = "YOUR_CONTENT_API_KEY"
class GhostContentApiUser(HttpUser):
wait_time = between(1, 3)
@task(4)
def browse_posts(self):
self.client.get(
f"/ghost/api/content/posts/?key={CONTENT_API_KEY}&limit=10&include=tags,authors",
name="GET Content API posts"
)
@task(2)
def browse_single_post_by_slug(self):
self.client.get(
f"/ghost/api/content/posts/slug/welcome/?key={CONTENT_API_KEY}&include=tags,authors",
name="GET Content API post by slug"
)
@task(2)
def browse_tags(self):
self.client.get(
f"/ghost/api/content/tags/?key={CONTENT_API_KEY}&limit=20",
name="GET Content API tags"
)
@task(1)
def site_settings(self):
self.client.get(
f"/ghost/api/content/settings/?key={CONTENT_API_KEY}",
name="GET Content API settings"
)When to use this scenario
This test is valuable if:
- Your Ghost frontend is headless
- Your theme fetches data client-side
- You use Ghost as a content backend for another app
- You want to isolate API performance from HTML rendering
What to look for
Pay attention to:
- Response times for collection endpoints like
/posts/ - Whether
include=tags,authorssignificantly increases latency - Error rates under concurrency
- Throughput differences between list and single-item queries
If these endpoints slow down under load, the issue may be database-related or caused by excessive query complexity.
Advanced Scenario 2: Testing Ghost member sign-in and account access
If your Ghost site uses memberships, authentication is a critical part of the user experience. Member login flows often involve email-based magic links in real production use, but for load testing you may need a staging-friendly or session-based approach depending on your implementation.
The example below demonstrates testing a member area using an existing authenticated session token. This is often the most practical approach for performance testing member-only content without relying on email delivery during the test.
from locust import HttpUser, task, between
class GhostMemberUser(HttpUser):
wait_time = between(2, 6)
def on_start(self):
# Example: preload a valid member session cookie captured from staging
self.client.cookies.set(
"ghost-members-ssr",
"REPLACE_WITH_VALID_SESSION_COOKIE",
domain="staging.your-ghost-site.com"
)
@task(4)
def view_members_only_post(self):
self.client.get("/members-only/market-analysis-q4/", name="GET member post")
@task(2)
def view_account_page(self):
self.client.get("/account/", name="GET /account/")
@task(2)
def view_archive(self):
self.client.get("/archive/", name="GET /archive/")
@task(1)
def view_premium_tag(self):
self.client.get("/tag/premium/", name="GET /tag/premium/")Why this approach works
Ghost member login is commonly based on secure email magic links, which are difficult to automate at scale in a clean load test. For realistic performance testing, many teams preload valid member sessions in staging and focus on the authenticated browsing behavior after login.
What this helps you measure
This scenario helps evaluate:
- Latency of gated content delivery
- Account page rendering performance
- Member session handling under load
- Whether premium content checks introduce measurable overhead
If your member pages are significantly slower than public pages, inspect theme logic, account widgets, membership integrations, and any custom portal scripts.
Advanced Scenario 3: Testing Ghost Admin API publishing workflows
Editorial performance matters too. If your team publishes frequently, bulk imports content, or runs scheduled workflows, you should test the Ghost Admin API in staging. This scenario uses JWT authentication with a Ghost Admin API key, which is how Ghost actually authenticates admin API requests.
import time
import uuid
import jwt
from locust import HttpUser, task, between
ADMIN_API_KEY = "YOUR_ADMIN_API_KEY" # format: id:secret
API_VERSION = "v5.0"
def build_ghost_admin_jwt(admin_api_key):
key_id, secret = admin_api_key.split(":")
iat = int(time.time())
exp = iat + 300
payload = {
"iat": iat,
"exp": exp,
"aud": f"/admin/"
}
token = jwt.encode(
payload,
bytes.fromhex(secret),
algorithm="HS256",
headers={"kid": key_id}
)
return token
class GhostAdminUser(HttpUser):
wait_time = between(3, 8)
def on_start(self):
token = build_ghost_admin_jwt(ADMIN_API_KEY)
self.headers = {
"Authorization": f"Ghost {token}",
"Content-Type": "application/json"
}
@task(3)
def list_posts(self):
self.client.get(
f"/ghost/api/admin/posts/?limit=15",
headers=self.headers,
name="GET Admin posts"
)
@task(1)
def create_draft_post(self):
unique_id = str(uuid.uuid4())[:8]
payload = {
"posts": [
{
"title": f"Load Test Draft {unique_id}",
"slug": f"load-test-draft-{unique_id}",
"status": "draft",
"html": "<p>This is a draft created during Ghost Admin API load testing with LoadForge.</p>",
"tags": [{"name": "load-testing"}, {"name": "staging"}]
}
]
}
self.client.post(
f"/ghost/api/admin/posts/",
json=payload,
headers=self.headers,
name="POST Admin create draft"
)Important note
Only run write-heavy admin tests against staging or a disposable Ghost environment. This script creates draft posts and should not be used against production without cleanup controls.
Why test admin workflows
This kind of performance testing is useful when:
- Editors complain that the admin dashboard feels slow
- Bulk publishing causes delays
- Content automation tools interact with Ghost Admin API
- You want to benchmark publishing throughput before a launch
What to monitor
Watch for:
- Increased latency on admin listing endpoints
- Post creation failures or rate-related errors
- Database or CPU spikes during write activity
- Slowdowns when reads and writes happen together
A powerful LoadForge strategy is to run public traffic and admin traffic simultaneously from separate user classes. That helps simulate real-world conditions where editors publish while readers browse.
Advanced Scenario 4: Mixed traffic model for realistic Ghost load testing
The most useful Ghost load testing often combines multiple traffic types. Readers browse public pages, members access premium content, and editors use the admin API. The script below models a mixed environment.
import time
import jwt
from locust import HttpUser, task, between
CONTENT_API_KEY = "YOUR_CONTENT_API_KEY"
ADMIN_API_KEY = "YOUR_ADMIN_API_KEY"
API_VERSION = "v5.0"
def build_ghost_admin_jwt(admin_api_key):
key_id, secret = admin_api_key.split(":")
now = int(time.time())
payload = {
"iat": now,
"exp": now + 300,
"aud": "/admin/"
}
return jwt.encode(
payload,
bytes.fromhex(secret),
algorithm="HS256",
headers={"kid": key_id}
)
class GhostReaderUser(HttpUser):
wait_time = between(1, 4)
@task(5)
def homepage(self):
self.client.get("/", name="Reader: /")
@task(3)
def post_page(self):
self.client.get("/2024/11/holiday-buying-guide/", name="Reader: post")
@task(2)
def tag_page(self):
self.client.get("/tag/reviews/", name="Reader: tag")
@task(2)
def content_api(self):
self.client.get(
f"/ghost/api/content/posts/?key={CONTENT_API_KEY}&limit=5&include=tags,authors",
name="Reader: Content API posts"
)
class GhostEditorUser(HttpUser):
wait_time = between(5, 10)
weight = 1
def on_start(self):
token = build_ghost_admin_jwt(ADMIN_API_KEY)
self.headers = {
"Authorization": f"Ghost {token}",
"Content-Type": "application/json"
}
@task
def admin_dashboard_data(self):
self.client.get(
"/ghost/api/admin/posts/?limit=10",
headers=self.headers,
name="Editor: Admin posts"
)Why this scenario matters
Mixed traffic tests are ideal for:
- Launch-day simulations
- Newsletter send traffic spikes
- Content-heavy commerce experiences
- Membership sites with simultaneous browsing and editorial activity
With LoadForge, you can scale this scenario across distributed cloud generators and compare how Ghost performs from different global test locations.
Analyzing Your Results
After running your Ghost load test, the next step is interpreting the results correctly. Raw request counts are not enough. Focus on the metrics that reveal real user experience and backend health.
Key metrics to review
Response time percentiles
Do not rely only on average response time. Look at:
- Median latency
- 95th percentile
- 99th percentile
Ghost may appear fast on average while a meaningful percentage of users experience slow page loads.
Requests per second
This tells you how much traffic Ghost can sustain. Compare throughput across:
- Homepage
- Post pages
- Tag pages
- Content API endpoints
- Admin API endpoints
Error rate
Any increase in:
- 500 errors
- 502/504 gateway errors
- 429 rate limits
- Authentication failures
should be investigated immediately.
Behavior under ramp-up
A healthy Ghost deployment should degrade gradually under load. If latency suddenly spikes at a specific concurrency level, that usually indicates a bottleneck in:
- Database connections
- Application workers
- Reverse proxy configuration
- Caching layer
- Theme rendering
Route-specific performance
Use named requests in Locust so LoadForge reports are easy to interpret. For Ghost, compare:
GET /GET /tag/.../GET member postGET Content API postsPOST Admin create draft
That makes it much easier to pinpoint whether issues affect public traffic, members, or editors.
Correlate with infrastructure telemetry
For best results, combine LoadForge test data with server metrics such as:
- CPU usage
- Memory utilization
- Database query time
- Cache hit ratio
- CDN response behavior
- Nginx or proxy queueing
LoadForge’s real-time reporting helps you see exactly when latency and errors begin, making it easier to match those points to backend resource saturation.
Performance Optimization Tips
If your Ghost load testing reveals slowdowns, these optimizations often provide the biggest wins.
Enable strong caching
Ghost sites benefit significantly from:
- CDN caching for images and static assets
- Reverse proxy caching where appropriate
- Browser caching headers for theme assets
This reduces origin load and improves content delivery speed.
Optimize your theme
Audit your Ghost theme for:
- Large images
- Excessive JavaScript
- Too many fonts
- Blocking third-party scripts
- Expensive dynamic homepage sections
A lightweight theme can dramatically improve load testing results.
Reduce API overfetching
If your frontend or theme uses the Content API, avoid requesting unnecessary relations or oversized payloads. For example, include=tags,authors is useful, but do not add extra fields unless needed.
Tune the database
Large Ghost sites may need database tuning, indexing review, and query analysis. Slow tag pages, archive pages, or member pages often point to database pressure.
Separate read and write testing
Publishing workflows and public browsing should be measured independently and together. This helps you understand whether write operations degrade reader experience.
Test from multiple regions
If your audience is global, use LoadForge global test locations to measure international latency and CDN effectiveness.
Common Pitfalls to Avoid
Ghost load testing is straightforward, but several mistakes can produce misleading results.
Testing only the homepage
A homepage-only test does not reflect real traffic. Include post pages, tags, archive routes, and APIs.
Ignoring cached versus uncached behavior
If every request hits the same URL, you may mostly measure cache performance. Use varied content paths to understand actual Ghost behavior.
Load testing production write endpoints
Do not test draft creation, publishing, or member management in production unless you have explicit controls and cleanup procedures.
Forgetting assets and frontend dependencies
Ghost performance is not just backend HTML generation. Heavy images, fonts, and scripts can dominate user-perceived latency.
Using unrealistic user pacing
Users do not refresh pages every 100 milliseconds. Set realistic wait times in Locust to simulate actual browsing patterns.
Not testing member-only experiences
If memberships are central to your Ghost business model, public-page testing alone is not enough. Include account pages, premium posts, and authenticated flows.
Overlooking newsletter-driven spikes
Ghost traffic often arrives in bursts after newsletter sends or social promotion. Run stress testing scenarios that model sudden surges, not just gradual ramp-ups.
Conclusion
Ghost is fast by design, but every real-world implementation is different. Your theme, member flows, APIs, infrastructure, and publishing patterns all affect how the platform performs under load. By running targeted load testing, performance testing, and stress testing against realistic Ghost workflows, you can identify bottlenecks before they impact readers, members, or editors.
With LoadForge, you can build realistic Locust-based Ghost tests, run them on distributed cloud infrastructure, monitor results in real time, and integrate performance testing into your CI/CD pipeline. Whether you are benchmarking a content-heavy CMS, validating a premium membership experience, or preparing for a high-traffic campaign, LoadForge gives you the visibility you need to keep Ghost fast and reliable.
If you are ready to benchmark Ghost CMS under real traffic conditions, try LoadForge and start building your first Ghost load test today.
LoadForge Team
LoadForge is a load and performance testing platform built on Locust. Our team has been shipping load tests against production systems since 2018, and we write these guides from real customer engagements.
Related guides
Keep going with more guides from the same category.

Contentful Load Testing: How to Load Test Contentful APIs with LoadForge
Learn how to load test Contentful APIs with LoadForge to measure content delivery performance and handle traffic surges.

Magento Load Testing: Performance Testing Magento Stores with LoadForge
Run Magento load tests with LoadForge to identify slow pages, optimize checkout flows, and validate store performance at scale.

Medusa Load Testing: How to Stress Test Medusa Commerce with LoadForge
Discover how to load test Medusa commerce apps with LoadForge to improve API speed, cart flows, and order handling at scale.