You might be wondering: “Why does performance even matter for a membership plugin? Isn’t WordPress already fast?”
Here’s the thing: regular WordPress sites are fast. But membership sites are different. They face a unique performance challenge that most people don’t understand until they build one.
This article explains why membership sites are inherently harder to make fast, and how BricksMembers solves this problem with optimizations that reduce database queries by up to 96% on certain pages.
The Caching Problem of Membership Sites
Here’s the dirty secret about membership sites: they’re almost impossible to cache effectively.
Regular WordPress sites are fast because of page caching. When someone visits your blog, the server generates the HTML once, saves it, and serves that cached HTML to the next 10,000 visitors. No database queries. No PHP processing. Just instant HTML delivery.
But membership sites can’t do this.
Why? Because every user sees different content:
- User A (Free member) sees: “Upgrade to Premium to access this course”
- User B (Premium member) sees: The actual course content
- User C (not logged in) sees: “Login to continue”
Same URL. Three completely different pages. You can’t cache that.
It gets worse with progress tracking:
- User A sees: “You’ve completed 5 out of 20 lessons (25%)”
- User B sees: “You’ve completed 15 out of 20 lessons (75%)”
- User C sees: “You’ve completed 0 out of 20 lessons (0%)”
Same course page. Different progress for every single user. You can’t cache that either.
And drip content makes it even worse:
- User A (joined yesterday) sees: Only Lesson 1 unlocked
- User B (joined 30 days ago) sees: All 20 lessons unlocked
- User C (completed Lesson 5) sees: Lessons 1-6 unlocked
Same course structure. Different unlocked content for every user based on their join date and completion status.
The result? Traditional page caching (WP Rocket, LiteSpeed Cache, Cloudflare) doesn’t help membership sites. Every page load requires:
- Checking who the user is
- Loading their membership levels
- Checking their progress
- Calculating what’s unlocked
- Rendering personalized content
This happens on every single page load for every single user. No caching. Just raw database queries and PHP processing.
This is why membership sites are slow.
BricksMembers solves this with a different approach: we can’t cache the final HTML, but we can cache the data. And we do it aggressively, at multiple levels, with optimizations that eliminate 96% of database queries.
This article explains exactly how we do it.
The Performance Problem with Membership Plugins
Let’s talk about why membership plugins can be slow.
The Traditional Approach
Most membership plugins use WordPress’s built-in parent-child relationships and post meta to organize content. Here’s what happens when a user loads a course page:
- Query the post (1 query)
- Check user access (1 query to get user meta, 1 query to get post meta)
- Get the course structure (1 query per level: course → module → lesson = 3 queries)
- Calculate progress (1 query per completed post to check parent relationships = 50+ queries for a 50-lesson course)
- Check drip unlocks (1 query per post to check prerequisites = another 50+ queries)
- Load navigation (1 query per sibling/parent/child = 20+ queries)
Total: 150+ database queries for a single page load.
Now multiply that by 100 concurrent users and you understand why membership sites can slow down.
BricksMembers changes that. Here’s how.
How BricksMembers Achieves Extreme Performance
We use a multi-layered approach to performance, with optimizations at every level of the stack.
Layer 1: Optimized Database Tables
Think of a database like a filing cabinet. WordPress uses one giant filing cabinet (wp_postmeta) where everything is mixed together. Finding information requires opening hundreds of drawers.
BricksMembers uses separate, organized filing cabinets for different types of information:
wp_brm_post_data – One drawer per post
- Stores which levels can access this post
- Stores where this post sits in your course structure
- Stores how many lessons are in this course
- One lookup = all the info we need
wp_brm_user_data – One drawer per user
- Stores which membership levels the user has
- Stores which posts the user completed (all in one place)
- One lookup = everything about this user
wp_brm_user_progress – Pre-calculated progress (optional if progress tracking is activated)
- Stores “User completed 15 out of 50 lessons (30%)”
- No need to count every time someone loads a page
- One lookup = instant progress display
wp_brm_user_unlocks – Drip content unlocks (optional if drip unlocks system is activated)
- Stores “Lesson 5 unlocked for User 123 on October 15”
- No need to recalculate unlock rules every time
- One lookup = instant unlock check
Why This Matters:
Imagine you want to know which lessons a user completed.
Traditional plugins: Open 50 separate drawers (one per lesson) to check each one
BricksMembers: Open 1 drawer that lists all completed lessons
Result: 50 lookups → 1 lookup
But Wait—Don’t Bigger Tables Slow Things Down?
You might be thinking: “If you’re storing more data in custom tables, won’t that make the database huge and slow?”
Great question. Here’s why the answer is no:
1. Indexes Make Size Irrelevant (Within Reason)
Database performance isn’t about table size—it’s about how the database finds data.
Think of it like a library:
- Bad library: 1,000 books thrown in a pile. Finding one book = search through all 1,000.
- Good library: 100,000 books organized with a card catalog. Finding one book = look up the catalog number, go straight to the shelf.
The good library is 100x bigger but infinitely faster because it’s indexed.
BricksMembers tables use MySQL indexes on every lookup field:
wp_brm_post_data: Indexed bypost_id(instant lookup by post)wp_brm_user_data: Indexed byuser_id(instant lookup by user)wp_brm_user_progress: Composite index onuser_id + boundary_id(instant lookup by user + scope)wp_brm_user_unlocks: Composite index onuser_id + post_id(instant lookup by user + post)
Result: Finding one user’s data in a table with 100,000 users takes the same time as finding it in a table with 100 users—about 0.0001 seconds.
2. How Traditional Plugins Store Data (And Why It’s Slow)
Most membership plugins use WordPress’s wp_usermeta table. There are two common approaches:
Approach 1: One row per completion
- Each completion = 1 row in
wp_usermeta - User completes 50 posts = 50 rows
- 25,000 users × 50 = 1.25 million rows
- Problem: Millions of rows mixed with all other user meta from every plugin
Approach 2: Serialized PHP array
- 1 row per user with serialized array:
a:50:{i:0;s:3:"123";...} - 25,000 users = 25,000 rows
- Problem: Can’t query inside serialized data—must load everything into PHP and process it there
Example: “Show me all users who completed post 123”
- Approach 1: Scan 2+ million rows in wp_usermeta → Slow
- Approach 2: Load all 25,000 rows, unserialize in PHP, check each array → Very slow
3. How BricksMembers Stores Data (Multi-Table Architecture)
BricksMembers keeps membership data in dedicated, purpose-built tables instead of cramming everything into wp_usermeta. That lets the database use the right indexes and return answers fast—especially on personalized pages.
The tables (and why):
brm_user_data– per-user JSON (levels, completion lists) for quick lookups.brm_post_data– per-post JSON (structure, ancestry, access rules).brm_user_progress– one row per user × parent post (course/module) when progress exists.brm_user_unlocks– one row per user × unlocked post (drip).brm_levels– level definitions (tiny).
Why this is fast
- Precomputed answers: progress totals and unlock state are written once, not recomputed on every request.
- Dedicated tables: clean keys, no “noise” from other plugins.
- JSON + indexes: modern MySQL can index JSON expressions, so lookups stay index-backed.
- Right tool for each job: completions in JSON (flexible), progress/unlocks in rows (fast joins/aggregations).
Example – “Show me all users who completed post 123”
Traditional (serialized): load 25k usermeta rows, unserialize in PHP, scan → slow.
BricksMembers (JSON index):
SELECT user_id
FROM brm_user_data
WHERE JSON_CONTAINS(completed_posts, '123');
Index-backed and predictable.
Size snapshot (large site: 25,000 users / 1,000 posts)
(upper-bound, high engagement; includes indexes)
| Table | What it stores | Approx. rows | Size |
|---|---|---|---|
| brm_user_data | Levels + completions (JSON) | 25,000 | ~61 MB |
| brm_post_data | Structure + access (JSON) | 1,000 | ~0.7 MB |
| brm_user_progress | Progress per user × parent post | ~5.25 M | ~420 MB |
| brm_user_unlocks | Drip unlocks per user × post | ~16.0 M | ~1.60 GB |
| brm_levels | Level definitions | ~200 | ~0.01 MB |
| Total | ~2.03 GB |
Rule of thumb for sizing:
Unlocks ≈ 0.64 × Users × Posts rows (100 MB per 1M rows)
Progress ≈ 0.21 × Users × Posts rows (80 MB per 1M rows)
User JSON ≈ 2.5 KB/user | Post JSON ≈ 0.7 KB/post
4. Storage at Scale
Upper-bound estimates (high engagement, includes indexes). Media is separate.
| Site size | Users | Posts | Estimated BRM storage |
|---|---|---|---|
| Small | 1,000 | 200 | ~18.7 MB |
| Medium | 10,000 | 500 | ~0.43 GB |
| Large | 25,000 | 1,000 | ~2.03 GB |
| Very large | 100,000 | 2,000 | ~16.0 GB |
| Enterprise Realistic | 1,000,000 | 1000 | ~83.3 GB |
Reality check on post counts:
“2,000 posts with progress + drip rules” is extremely unlikely. Even 1,000 tracked posts is rare – which user goes through 1000 lessons? Most serious memberships operate around 50–400 lesson tracked/dripped posts total. In practice, storage growth is driven far more by users than by posts.
What Actually Fills Your Storage
- Images/PDFs: 3–10 GB (thumbnails, worksheets, downloads).
- WordPress core + plugins/themes: 0.5–2 GB.
- Database (all tables): often 0.2–1.0 GB for mid-size sites.
- BricksMembers (part of DB): MB → low-GB, depending on users.
- Backups: 3–10 GB (many hosts keep these off-box).
Important Tip
Never host course videos on WordPress. Use Vimeo/Gumlet/Wistia/etc. for adaptive streaming, global CDN, analytics, and pennies/GB storage. With video offsite, media outweighs BRM data by 20–100×.
The Cost Perspective
- 100k users / 2k posts → ~16 GB of BRM data. Fits standard 50+ GB tiers.
- 1M / 1k → ~83.3 GB. You’re on managed DB/VM—tens of dollars/month extra storage.
Trade-off that wins: spend predictable, linear disk to avoid per-request recomputation. Personalized pages make far fewer queries and stay fast under load. The performance gains are worth far more than the storage costs. Especially at that scale, where concurrent requests become frequent.
5. Organized Data = Faster Queries
Here’s the real performance killer: searching through mixed data.
WordPress’s wp_usermeta table (used by traditional plugins and especially custom solutions) contains:
- User profile data (bio, description, etc.)
- Plugin settings and preferences
- Session tokens
- Membership data (if using Approach 1: separate rows)
- E-commerce data (order history, cart, etc.)
- Social media connections
- Everything else from every plugin
All mixed together in one giant table. Finding membership data requires filtering through millions of unrelated rows.
Example: A typical site with 25,000 users might have:
- 2,000,000+ rows in
wp_usermeta(80+ meta keys per user from various plugins) - Only 1,250,000 of those rows are membership completions (if using Approach 1)
- Every query must filter through ALL 2 million rows to find the relevant ones
BricksMembers tables contain ONLY membership data.
When we query wp_brm_user_data, every single row is relevant. No filtering needed. The database can use indexes efficiently because there’s no noise.
Example: Same site with 25,000 users:
Queries are 80x faster because there’s no unrelated data to filter through
25,000 rows in wp_brm_user_data (1 per user)
ALL 25,000 rows are membership data
6. JSON Storage Is Efficient
You might think: “JSON in the database? Isn’t that slow?”
Not anymore. Modern MySQL (5.7+) has native JSON support with:
- JSON indexes: Query specific fields inside JSON without parsing the whole thing
- JSON functions: Extract, search, and filter JSON data at the database level
- Compact storage: JSON is stored in binary format, not as text
BricksMembers uses MySQL’s JSON features to:
- Store arrays of completed posts in one field instead of 50 separate rows
- Store structure paths with ancestry and navigation in one field
- Query JSON fields with indexes for fast lookups
Example: Finding all posts in a specific structure:
BricksMembers approach: Query wp_brm_post_data with JSON index on structure_path->structure_id→ Instant lookup using index
Traditional approach: Query wp_postmeta for all posts with meta_key = 'structure_id' and meta_value = 'wordpress-mastery' → Scan millions of rows
7. We Clean Up After Ourselves
BricksMembers automatically maintains database efficiency:
- When a user is deleted: All their progress, unlocks, and data are removed
- When a post is deleted: All references in structure paths, progress, and unlocks are cleaned up
- When drip rules change: Old unlock records are updated or removed as needed
- When progress tracking is disabled: Progress data can be optionally cleared
No orphaned data. No bloat. Just clean, efficient tables.
Bottom Line on Size
Yes, BricksMembers stores more data than traditional plugins.
But:
- ✅ It’s organized in dedicated tables (not mixed with everything else)
- ✅ It’s properly indexed (instant lookups regardless of size)
- ✅ It’s stored efficiently (JSON binary format where it makes sense, not separate rows)
- ✅ It’s automatically cleaned up (no orphaned data)
- ✅ The total size is tiny compared to the performance gains
The result? Faster queries, not slower ones. The “extra” data we store is what makes the plugin fast—it’s pre-computed answers that eliminate expensive calculations on every page load.
Think of it like this: Would you rather do 1,000 math problems every time someone asks you a question, or write down the answers once and just read them back? BricksMembers writes down the answers.
Layer 2: Pre-Computed Structure Paths
Imagine you’re looking at Lesson 12 and want to know which course it belongs to.
Traditional approach:
- Check Lesson 12’s parent → finds Module 3
- Check Module 3’s parent → finds Course 1
- Now you know Lesson 12 is in Course 1
That’s 3 separate lookups just to find the course.
BricksMembers approach:
Let’s look at a 4-level structure: Course → Module → Lesson → Video
Example 1: A Video (bottom level)
{
"structure_id": "wordpress-mastery",
"ancestry_ids": {
"course": [123, 1],
"module": [456, 3],
"lesson": [789, 5]
},
"nav": {
"next_id": 791,
"prev_id": 790
}
}
Translation:
- This video belongs to Lesson 789 (and it’s the 5th video in that lesson)
- That lesson is in Module 456 (which is the 3rd module in the course)
- That module is in Course 123 (which is the 1st course in the structure)
- Next video is 791, previous is 790
Example 2: A Lesson (has video posts as children)
{
"structure_id": "wordpress-mastery",
"ancestry_ids": {
"course": [123, 1],
"module": [456, 3]
},
"nav": {
"next_id": 790,
"prev_id": 788
},
"boundaries": {
"video": {
"global": {"min": 1, "max": 12},
"count": 12
}
}
}
Translation:
- This lesson is in Module 456 (which is the 3rd module in the course)
- That module is in Course 123 (which is the 1st course in the structure)
- Next lesson is 790, previous is 788
- This lesson has 12 videos (positions 1-12)
Why the position numbers matter:
The second number in each pair (like [123, 1]) tells us the position within the parent based on menu order inside its post type – no worries, we ensure it’s updated every time the order changes. This is used for:
- “Require ALL previous items” drip rule: If this is lesson 15, we need to know “get me lessons 1-14” (we use the position to query the first 14 items)
- Scheduled drip: “Unlock 3 lessons every 7 days” (position 1-3 unlock immediately, 4-6 unlock after 7 days, etc.)
- Progress calculations: When calculating percentages across boundaries
Why boundaries matter:
When you want to show “all videos in this lesson,” traditional plugins have to check every single video in your entire site to see if it belongs to this lesson. That’s slow.
BricksMembers stores the answer directly in the lesson: “Videos 1-12 belong to this lesson.” One lookup, instant answer.
Note: Only parent posts have boundaries (posts with children). Bottom-level posts (like videos in this example) don’t have boundaries because they have no children.
Result: 3+ lookups → 0 lookups (already have all the answers)
Layer 3: Three-Tier Caching Strategy
Even with organized filing cabinets, opening drawers takes time. So we use a smart caching system.
Think of it like this:
Tier 1: Your Desk (Instant)
When you’re working on something, you keep it on your desk. Need it again? It’s right there.
BricksMembers does the same thing. When we look up your progress once, we keep it in memory. Need it again on the same page? Instant.
Example: You have a progress bar at the top and a “15/50 lessons complete” tag at the bottom. We look up your progress once, then reuse it. No second lookup needed.
Tier 2: Your Bookshelf (Fast)
Some information you use often but not constantly. You keep it on a nearby bookshelf.
BricksMembers stores frequently-used data in WordPress Object Cache (Redis, Memcached, or transients). This data stays available for 15 minutes.
Example: Your membership levels don’t change often. We cache them so every page load doesn’t need to check the database.
Tier 3: The Filing Cabinet (Slow)
When you need something for the first time, you have to go to the filing cabinet.
BricksMembers only queries the database when data isn’t on your desk (Tier 1) or bookshelf (Tier 2).
Example: First time loading your membership levels → Database query → Store in Object Cache (Tier 2) and Request Registry (Tier 1) → Next time it’s instant from cache.
Layer 4: Batch Loading for Query Loops
Imagine you’re showing a page with 100 courses. Each course needs to display:
- Progress (15/50 lessons complete)
- Access status (locked/unlocked)
- Drip status (available now/unlocks Oct 15)
The slow way: Check each course one by one
- Course 1: Check progress, check access, check drip
- Course 2: Check progress, check access, check drip
- Course 3: Check progress, check access, check drip
- …100 times
That’s 300+ database lookups.
The BricksMembers way: Load everything at once
Before showing any courses, we:
- Get the list of all 100 course IDs (got it already before from the query loop filters)
- Load ALL progress data for these 100 courses in ONE query
- Load ALL access data for these 100 courses in ONE query
- Load ALL drip data for these 100 courses in ONE query
- Store everything in memory (Tier 1 cache – your desk)
Now when we display each course, the data is already there. Zero additional lookups.
Result: 300+ lookups → 3-4 lookups (up to 99% reduction in query loops)
Real-World Example:
Page with 10 courses, 299 lessons, using progress tags and drip filters:
Without batch loading: 950 database queries, ~25ms database time
With batch loading: 40 database queries, ~4ms database time
Result: 96% fewer queries, 84% faster
This is a complex page with query loops, progress tracking, and drip content. Simpler pages see smaller but still significant improvements.
Layer 5: Chunking for Large Sites
What if you have 2,000 lessons? Loading all 2,000 at once could overwhelm your server.
Our solution: Break it into smaller chunks.
Instead of:
- 1 giant query for 2,000 lessons (might crash)
We do:
- 1 query for lessons 1-600
- 1 query for lessons 601-1200
- 1 query for lessons 1201-1800
- 1 query for lessons 1801-2000
Result: 4 queries instead of 2,000, and your server stays happy.
Realisticcally, this applies mostly to the backend when you update posts. So we even keep that fast.
Layer 6: Pre-Calculated Progress
Imagine showing “You completed 15 out of 50 lessons (30%)”.
The slow way: Count every time
- Count how many lessons are in the course (1 lookup)
- Count how many the user completed (1 lookup)
- Calculate the percentage
- Do this every time someone loads the page
The BricksMembers way: Calculate once, store the answer
We store: “User 456 completed 15 out of 50 lessons in Course 123”
When you load the page, we just read this pre-calculated answer. No counting needed.
Even better: We let the database do the math
We only store two numbers in the database:
- Completed count: 15
- Total items: 50
The database automatically calculates the percentage (15 ÷ 50 = 30%) using a MySQL generated column. This means even the percentage calculation happens in the database, not in PHP, making it even faster.
When do we recalculate?
- User completes a lesson → Update their progress for that course
- Admin adds a lesson → Mark the course as “needs recalculation”
- Next time someone loads the page → Recalculate and store the new answer
Result: Instant progress display, no counting on every page load, and the database does the math for us
Layer 7: Pre-Calculated Drip Unlocks
Drip content means lessons unlock based on rules:
- “Unlock 7 days after joining”
- “Unlock after completing Lesson 4”
- “Unlock on October 15”
The slow way: Check the rules every time
- Check when the user joined
- Check if they completed the prerequisites
- Check if the date has passed
- Combine all the rules
- Do this for every lesson on every page load
The BricksMembers way: Calculate once, store the answer
We store: “Lesson 5 is unlocked for User 456”
When you load the page, we just check if this record exists. No rule evaluation needed.
When do we recalculate?
- User completes a prerequisite → Immediately check what new lessons unlock
- Every 12 hours → Automatic background job checks time-based unlocks (like “unlock on October 15”)
- Admin changes drip rules → Recalculate for all users (in batches)
- In preservation mode, only unlocks are added but not removed to avoid annoying the student
This means users see newly unlocked content based on dates/times without having to visit the site.
Result: Instant unlock checks, no rule evaluation on every page load
Layer 8: Smart Handling of Empty Data
Here’s a tricky problem: What if a user hasn’t started a course yet?
There’s no progress data in the database. So what happens when you try to show “0/50 lessons complete”?
The slow way: Keep checking
- Check database for progress → Find nothing
- Show “0/50” on the page
- Next progress tag → Check database again → Find nothing again
- Keep checking every time
The BricksMembers way: Remember “nothing”
When we batch-load progress for 10 courses and only find data for 2, we:
- Store the 2 courses with real progress
- Create “empty” records for the other 8 courses (0/50, 0/32, etc.)
- Store these empty records in cache too
Now when the next progress tag asks about Course 3, we say “We already checked—it’s 0/50.” No need to check the database again.
Result: One batch lookup instead of repeated “is there data?” checks
Why This Matters for Membership and LMS Sites
Performance isn’t just about bragging rights. It directly impacts your business.
User Experience
Slow sites lose students.
Studies show that 53% of mobile users abandon sites that take longer than 3 seconds to load. For online courses, where users are already fighting distraction, every second counts.
BricksMembers is designed to keep pages loading quickly, even with progress bars, drip unlocks, and navigation elements.
Hosting Costs
Slow plugins require expensive hosting.
When a plugin makes hundreds of database queries per page, you need powerful servers to handle the load. This can mean expensive dedicated hosting.
BricksMembers’ efficient database design and optimizations at every stage means you can run larger sites on standard managed WordPress hosting.
Scalability
Slow plugins hit walls.
As your membership site grows, inefficient plugins slow down. What worked fine with 100 users becomes unusable with 1,000 users.
BricksMembers is designed to scale. The same optimizations that make it fast for 100 users keep it fast as you grow.
Admin Productivity
Slow admin pages waste time.
When your admin dashboard takes 10 seconds to load, you waste time just waiting for pages to render.
BricksMembers admin pages are optimized to load quickly, even with large amounts of content.
For intensive operations, we show progress bars
When you make changes that require background processing (like updating drip rules or reordering content), we show a real-time progress bar so you always know something is happening. No more wondering if the page froze or if it’s still working.
Automatic performance adjustments
BricksMembers automatically detects your server’s performance and adjusts batch sizes accordingly:
- Weak servers (shared hosting): Smaller batches, longer intervals
- Average servers (managed WordPress): Balanced settings
- Good servers (VPS/dedicated): Larger batches, faster processing
This means the plugin works efficiently on any hosting tier, from budget shared hosting to enterprise servers.
Real-World Performance Metrics
Here are actual measurements from a test site with 10 courses and 299 lessons, measured using BricksMembers’ built-in query counter:
Page with query loop showing 10 courses + progress tags + drip filters:
Note: The 950 baseline includes the snapshot system. The batch loading optimization specifically targets query loops with progress and drip features.
| Metric | Without Batch Loading | With Batch Loading | Improvement |
|---|---|---|---|
| BRM Queries | 950 | 40 | 96% reduction |
| Database Time | ~25ms | ~4ms | 84% faster |
Individual course page with progress bar:
| Metric | Before | After | Improvement |
|---|---|---|---|
| BRM Queries | ~25 | ~3 | up to 88% reduction |
| Database Time | ~8ms | ~1.5ms | up to 81% faster |
Simple membership page (access check only):
| Metric | Before | After | Improvement |
|---|---|---|---|
| BRM Queries | ~5 | ~2 | up to 60% reduction |
| Database Time | ~2ms | ~0.8ms | up to 60% faster |
Performance varies by page complexity:
- Pages with query loops showing many posts: up to 96% reduction
- Pages with progress tracking and drip content: up to 88% reduction
- Simple access-protected pages: up to 60% reduction
- Pages without BRM features: No BRM queries (nothing to optimize)
In future versions, we will try to expand our snapshot and batching system to native WP/Bricks data as much as possible. So you might see even better performance soon.
How to Maximize Performance
BricksMembers is fast by default, but you can make it even faster:
1. Enable Object Caching
Install Redis or Memcached on your server. This moves the object cache from database transients to in-memory storage.
Impact: Faster cache lookups (data retrieval from memory instead of database)
How to enable:
- Ask your host to enable Redis (most managed hosts offer this)
- Install the Redis Object Cache plugin
- Activate it
2. Enable Batch Loading in Query Loops
When you use BricksMembers query filters (Access, Progress, Drip, or Boundary filters), batch loading is automatically enabled. You don’t need to do anything.
If you’re using a query loop with BricksMembers dynamic tags but without BRM filters, you can manually enable batch loading:
How to enable:
- Edit your query loop element in Bricks – ensure query loop is turned on!
- In the Content Tab, find the BricksMembers section
- Check “Enable Batch Loading”
- Save
Impact: Up to 96% query reduction in query loops with progress and drip features (based on test with 10 courses and 299 lessons)
Note: This checkbox only appears when you’re NOT using BRM query filters (since they auto-enable batch loading).
3. Keep WordPress and Plugins Updated
Update regularly. We continuously optimize BricksMembers.
Performance Monitoring
BricksMembers includes a built-in query counter to track performance in real-time.
How to enable:
- Go to BricksMembers → Tools → Benchmark
- Find the Query Counter card at the top
- Check “Enable Query Counter (Frontend)”
- Click “Save Settings”
- Visit any frontend page as admin
You’ll see a floating box in the bottom-right corner showing:
- Number of BRM database queries
- BRM database time
- Total WordPress queries
- Percentage of queries from BricksMembers
Use it to:
- Verify optimizations are working
- Identify slow pages
- Compare before/after when making changes
- Demo performance to clients
Important: The query counter itself also adds queries, which it does not count. But for best performance, we recommend turning it off after your tests.
The Bottom Line
BricksMembers is fast because we’ve optimized every layer of the stack:
- Custom database tables optimized for membership data
- Pre-computed structure paths eliminate recursive queries
- Three-tier caching (Request Registry → Object Cache → Database)
- Snapshot system pre-loads data per boundary for instant access
- Batch loading loads all query loop data in 3-4 queries instead of hundreds
- Smart progress calculation only recomputes when needed
- Pre-calculated drip unlocks stored for instant checks
- Empty placeholders prevent unnecessary re-queries
The result? A membership and LMS plugin that’s significantly faster than traditional solutions, scales easily to tens of thousands of users, and runs on standard hosting.
You don’t need a dedicated server. You don’t need to hire a performance consultant. You just need BricksMembers.
