Hybrid load architecture
Protocol load testing and browser testing answer different questions. If you run them separately, you get two data points with no link between them. You cannot tell whether the LCP degradation in your Playwright check happened during the peak load window. The hybrid load pattern runs both in the same MaxoPerf run, at the same time.
Before you start
Section titled “Before you start”- Read Browser vs protocol load to learn what each approach measures.
- Read Selenium performance testing to learn how browser VUs work in MaxoPerf.
- Read Frontend web vitals under load for the web-vitals capture pattern used inside the browser VU script.
The hybrid pattern
Section titled “The hybrid pattern”The hybrid architecture uses two executors in the same Taurus YAML:
- Many protocol VUs (JMeter, k6, or Taurus HTTP) stress the backend at realistic scale. They generate the API load your server has to handle.
- A few browser VUs (Taurus
seleniumexecutor) sample the user experience during the load. They answer one question: what does a user see while the API is under pressure?
Both run at the same time. The protocol VUs generate load and the browser VUs measure UX. MaxoPerf collects results from both and shows them in the same run-detail view.
Pattern 1: VarioTest (recommended)
Section titled “Pattern 1: VarioTest (recommended)”VarioTest is the MaxoPerf feature that coordinates several tests in a single run. Create one test for the protocol load and one for the browser check, then combine them in a VarioTest:
- Protocol test: your existing JMeter or k6 test against the API endpoints. Set concurrency to your target peak (e.g. 200 VUs, 15 min hold).
- Browser test: a Taurus
seleniumtest with 3–5 browser VUs running the user journey. Use the same hold duration (15 min). - VarioTest: combine the two tests. MaxoPerf starts both at the same time and collects results in a single run.
The VarioTest Overview tab shows protocol throughput and latency next to browser iteration timing. That links cause and effect: “at 14:32, when API p95 climbed to 800 ms, the browser LCP measurement was 4.1 s.”
Pattern 2: Two simultaneous MaxoPerf runs
Section titled “Pattern 2: Two simultaneous MaxoPerf runs”If you have not set up VarioTest yet, start both tests by hand at the same time and line them up by timestamp:
- Start the protocol load run in MaxoPerf.
- Wait for the ramp-up to finish (on the Overview tab, throughput levels off).
- Start the browser test run in MaxoPerf.
- When both finish, open both run-detail pages and compare timestamps on the latency charts.
This is less automated than VarioTest, but it works right away with no extra configuration.
Example Taurus YAML: browser check only (companion to protocol load)
Section titled “Example Taurus YAML: browser check only (companion to protocol load)”This YAML runs the browser half of the hybrid. Run it as a separate MaxoPerf test alongside your protocol load test:
execution: - executor: selenium concurrency: 5 # 5 browser VUs — enough for UX sampling, not load generation ramp-up: 1m hold-for: 15m # match the protocol load hold duration scenario: hybrid-browser-check
scenarios: hybrid-browser-check: script: scripts/hybrid_check.py browser: chrome headless: true
modules: selenium: chromedriver: version: latestfrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as EC
def test_hybrid_ux_check(driver): """ UX check run during protocol load. Captures TTFB and load time. Assertion failures appear as errors in MaxoPerf results. """ driver.get("https://app.example.com/dashboard")
# Wait for main content (reflects both server and render time) WebDriverWait(driver, 20).until( EC.presence_of_element_located((By.CSS_SELECTOR, "[data-testid='dashboard-content']")) )
# Capture timing timing = driver.execute_script(""" const nav = performance.getEntriesByType('navigation')[0]; return { ttfb: nav.responseStart - nav.requestStart, loadComplete: nav.loadEventEnd - nav.startTime }; """)
# Hard gate: fail the browser check if load time exceeds SLO assert timing['ttfb'] < 800, f"TTFB {timing['ttfb']:.0f} ms > 800 ms SLO under load" assert timing['loadComplete'] < 4000, ( f"Load {timing['loadComplete']:.0f} ms > 4 s SLO under load" )
print(f"TTFB: {timing['ttfb']:.0f} ms | Load: {timing['loadComplete']:.0f} ms")What a hybrid run looks like in MaxoPerf
Section titled “What a hybrid run looks like in MaxoPerf”import Screenshot from ‘@components/Screenshot.astro’;
In the Overview tab:
- Protocol throughput. The high-RPS line from JMeter or k6 VUs. This is the backend load.
- Browser iteration rate. The low, steady line from Selenium VUs. Each iteration is one completed browser flow.
- Browser error rate. Assertion failures from the browser check. A spike here during the protocol load plateau means the front end degraded past your SLO.
- Correlation point. Find the moment protocol p95 latency rises and check whether browser load times rise at the same timestamp. You see the cause directly instead of guessing it.
Sizing the hybrid run
Section titled “Sizing the hybrid run”| Protocol VUs | Browser VUs | Use case |
|---|---|---|
| 50–200 | 2–3 | Development / staging check |
| 200–500 | 3–5 | Pre-release peak simulation |
| 500–1000 | 5–10 | Major launch readiness |
| 1000+ | 5–10 | Use protocol VUs for scale; browser count stays low |
The browser VU count does not need to grow with protocol VUs. You need enough browser samples to detect degradation. Typically 3–10 VUs iterating through the hold period give reliable timing data.
Do / don’t
Section titled “Do / don’t”Do:
- Keep browser VUs at 5–10 even when protocol VUs reach 500+. More browser VUs do not improve the measurement.
- Assert on web vitals thresholds in the browser script so degradation shows as an error in the MaxoPerf result, not as a number you have to read by hand.
- Run the hybrid against staging with production-like data. Browser VUs react to data volume (an empty database gives an unrealistically fast LCP).
Don’t:
- Scale browser VUs in proportion to protocol VUs. The two answer different questions and need different counts.
- Skip the browser check during peak-load simulation. That is when front-end degradation is most likely.
- Use the hybrid pattern for pure throughput / breakpoint tests. Add browser VUs only when UX measurement is part of the goal.
Where to go next
Section titled “Where to go next”- Frontend web vitals under load: the web-vitals capture pattern used inside the browser VU script.
- Daily browser performance scenarios: concrete how-to-run examples for checkout, login, and marketing-launch checks.
- Selenium performance testing: browser VU configuration reference.
- By engine: Taurus executor catalog: all 21 Taurus executors, including
seleniumandwdio.