How to Record & Automate Synthetic Web Transaction Test Scripts: An SRE Playbook
Simple HTTP GET status checks verify only that an edge server or reverse proxy returns a 200 OK response. They cannot detect whether an authentication redirect loop broke, a client-side JavaScript bundle failed to mount, or a payment gateway iframe throws a cross-origin DOM exception during checkout.
Synthetic web transaction monitoring executes real browser journeys—such as logging in, selecting items, submitting multi-step forms, and verifying checkout confirmations—from distributed vantage points around the world. This playbook outlines how Site Reliability Engineers (SREs) record, refactor, parameterize, and automate headless browser scripts with Playwright to catch revenue-impacting regressions before end users do.
1. Synthetic Transaction Architecture
Synthetic monitoring treats end-user transactions as distributed state machines running through headless browser engines:
Synthetic Orchestrator (Cron / Worker)
│
├─► 1. Launch Isolated Browser Context (Chromium / Firefox / WebKit)
├─► 2. Ingest Secrets from Vault / Cloud Secrets Manager
├─► 3. DNS Lookup & Transport Handshake (TCP + TLS 1.3)
├─► 4. Navigate Initial Route & Render DOM
├─► 5. Perform Actions (Type, Click, Select, Scroll)
├─► 6. Intercept XHR / Fetch API Responses
├─► 7. Evaluate Business Assertions (DOM Text, Status Elements)
└─► 8. Capture HAR, Console Logs & Trace Artifacts on Failure
Unlike passive Real User Monitoring (RUM), synthetic transactions produce deterministic baselines with zero dependency on organic user traffic, enabling continuous verification even during off-peak hours.
2. Choosing the Right Recording Strategy
When automating complex web workflows, select the tool that balances development speed against ongoing test maintenance:
| Recording Approach | Fidelity | Maintenance Overhead | Network Visibility | Best Production Use Case |
|---|---|---|---|---|
| Playwright Codegen | High | Low - Medium | High | Modern SPA/SSR apps (React, Next.js, Vue). |
| Selenium IDE | Medium | High | Low | Legacy Java test automation estates. |
| HAR Capture & Replay | Medium | Low | Very High | Headless API regression and payload verification. |
| Raw HTTP / API Scripts | Low - Medium | Low | Maximum | Microservice health and backend auth tokens. |
| Hand-Crafted Playwright | Maximum | Medium | High | Mission-critical checkout and login journeys. |
3. Recording a Journey with Playwright Codegen
To record a multi-step user transaction, launch the Playwright code generator:
# Launch interactive browser recorder with target URL
npx playwright codegen https://app.example.com/login --output=tests/synthetic/checkout.spec.ts
Refactoring Raw Recorder Output
Raw recorder output frequently contains fragile CSS selectors (e.g., .css-1x9abc7) and hardcoded credentials. Refactor the script into resilient, parameterized TypeScript:
import { test, expect } from '@playwright/test';
test('Golden Path: User Authentication and Workspace Navigation', async ({ page }) => {
// 1. Navigate to target URL with explicit timeout
await page.goto('https://app.example.com/login', { timeout: 15000, waitUntil: 'networkidle' });
// 2. Use semantic, accessible locator labels
await page.getByLabel('Work Email').fill(process.env.SYNTHETIC_USER_EMAIL!);
await page.getByLabel('Password').fill(process.env.SYNTHETIC_USER_PASSWORD!);
await page.getByRole('button', { name: 'Sign in' }).click();
// 3. Web-first assertion: Verify authenticated dashboard load
const dashboardHeading = page.getByRole('heading', { name: 'Production Overview' });
await expect(dashboardHeading).toBeVisible({ timeout: 10000 });
// 4. Verify account status badge
const statusBadge = page.locator('[data-testid="subscription-tier"]');
await expect(statusBadge).toHaveText('Enterprise Active');
});
4. Capturing Protocol-Level Network Timings & HAR Artifacts
To isolate whether a transaction failure stems from network degradation or frontend rendering, configure Playwright to record full HTTP Archive (HAR) logs:
import { test, expect } from '@playwright/test';
test('Capture HAR and Network Performance Metrics', async ({ browser }) => {
const context = await browser.newContext({
recordHar: {
path: 'artifacts/checkout-network.har',
content: 'embed',
mode: 'minimal',
},
viewport: { width: 1920, height: 1080 },
});
const page = await context.newPage();
const startTime = Date.now();
await page.goto('https://app.example.com/checkout');
await page.getByTestId('pay-button').click();
await expect(page.getByText('Payment Succeeded')).toBeVisible();
const totalDuration = Date.now() - startTime;
console.log(`Transaction Completed in ${totalDuration}ms`);
await context.close();
});
Wire-Level Diagnostic Inspection
When synthetic transactions report elevated TTFB or connection timeouts, test the underlying edge transport directly using curl:
# Deconstruct DNS, TCP, TLS, and TTFB network breakdown
curl -sS -o /dev/null \
-w 'DNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\nHTTP: %{http_code}\n' \
https://app.example.com/api/v1/checkout/health
5. SRE Synthetic Latency Threshold Matrix
Establish rigorous SLA targets for every phase of synthetic transaction execution:
| Step / Signal | Healthy Baseline | Warning Latency | Critical Incident Threshold | Failure Mode |
|---|---|---|---|---|
| DNS Resolution | (< 50\text{ ms}) | (50\text{ ms} - 150\text{ ms}) | (> 150\text{ ms}) | Authoritative DNS / Anycast routing latency. |
| TCP Connection | (< 100\text{ ms}) | (100\text{ ms} - 300\text{ ms}) | (> 300\text{ ms}) | WAN network congestion, packet retransmits. |
| TLS 1.3 Handshake | (< 150\text{ ms}) | (150\text{ ms} - 400\text{ ms}) | (> 400\text{ ms}) | Edge certificate negotiation, cipher mismatch. |
| TTFB (First Byte) | (< 300\text{ ms}) | (300\text{ ms} - 800\text{ ms}) | (> 800\text{ ms}) | Backend worker starvation, database bottlenecks. |
| Full Transaction | (< 2.5\text{ s}) | (2.5\text{ s} - 6.0\text{ s}) | (> 6.0\text{ s}) | Client JavaScript execution, DOM rendering stalls. |
| Success Rate | (\ge 99.9%) | (99.0% - 99.89%) | (< 99.0%) | Transaction error budget exhaustion. |
Transaction Error Budget Formula
Calculate your monthly allowable synthetic failure budget:
[E = 1 - \text{SLO}]
For a (99.9%) transactional availability objective:
[E = 1 - 0.999 = 0.001 \quad (0.1% \text{ allowable failure rate})]
Calculate your transaction error budget and allowable downtime. Use our free SLA Calculator to evaluate allowable outage minutes across monthly intervals, and convert frequency schedules with the Cron Translator.
6. Automating Scheduled Synthetic Execution
Deploy synthetic test runners as recurring Kubernetes CronJobs across multiple geographical cloud regions:
apiVersion: batch/v1
kind: CronJob
metadata:
name: synthetic-checkout-monitor
namespace: observability
spec:
schedule: "*/5 * * * *" # Runs every 5 minutes
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
jobTemplate:
spec:
backoffLimit: 1
template:
spec:
restartPolicy: Never
containers:
- name: playwright-runner
image: mcr.microsoft.com/playwright:v1.44.0-jammy
command: ["npx", "playwright", "test", "tests/synthetic/checkout.spec.ts"]
env:
- name: SYNTHETIC_USER_EMAIL
valueFrom:
secretKeyRef:
name: synthetic-credentials
key: email
- name: SYNTHETIC_USER_PASSWORD
valueFrom:
secretKeyRef:
name: synthetic-credentials
key: password
7. SRE Troubleshooting Runbook for Failed Synthetic Transactions
When an automated transaction alert triggers, execute this 10-step diagnostic runbook:
- Classify the failure layer: DNS lookup, transport handshake, HTTP 5xx, selector timeout, or business assertion mismatch.
- Inspect the Playwright trace viewer zip file and recorded screenshots to identify where the browser journey halted:
npx playwright show-trace artifacts/trace.zip - Check console error logs captured during the run for uncaught JavaScript exceptions or blocked cross-origin assets.
- Evaluate the recorded HAR file to inspect network response bodies for backend API errors (
401 Unauthorized,429 Too Many Requests,500 Internal Server Error). - Reproduce the transaction locally or from a regional bastion host using identical test credentials.
- Correlate the exact timestamp and
x-request-idheader against ingress load balancer logs and distributed APM traces. - Verify whether the failure is global or isolated to a specific cloud region or edge CDN node.
- Quarantine flaky or broken test scripts temporarily to prevent on-call alert fatigue while investigating application regressions.
- Deploy application or infrastructure fixes, verifying that synthetic test runs succeed across all monitored regions.
- Document the root cause in an incident post-mortem and add new assertion checks to prevent regression recurrence.
8. 16-Point Synthetic Testing Production Checklist
Verify that your synthetic monitoring estate conforms to these operational standards:
- All critical user conversion funnels (Login, Search, Checkout, API Key Generation) scripted.
- Semantic locators (
getByRole,getByLabel,getByTestId) used instead of volatile CSS classes. - Synthetic credentials injected securely from secret managers with dedicated non-admin accounts.
- Test runs scheduled across multiple geographical regions to catch localized CDN / ISP faults.
- Screenshots, console logs, and HAR files captured automatically on failure.
- Web-first assertions used with explicit timeout limits (
5s - 10s). - Execution schedules configured and validated using the Cron Translator.
- Synthetic test error budgets calculated using the SLA Calculator.
- Concurrency policies configured to prevent overlapping test executions.
- In-flight test data cleaned up or isolated using deterministic idempotency keys.
- Automated alerts routed to on-call engineers via Slack, Telegram, or PagerDuty.
- External end-to-end synthetic monitoring configured in Pingzo for 24/7 global transaction verification.
Stop Finding Out About Outages from Angry Users
Get instant WhatsApp & Discord alerts the second your API, website, or server goes down. Setup in 30 seconds with 60-second checks.