A realistic BAW load test simulates the user journeys (open task list, open the task - which loads the coach -, submit) and the system paths (instances started by integrations, timers), not raw REST calls per second. Skeleton with k6 (JMeter works the same with one HTTP sampler per step and a JSON extractor for the CSRF token):
// k6 script - one virtual user = one clerk: login, list, claim, open coach, complete; think times between steps
import http from 'k6/http'; import { sleep, check } from 'k6';
export const options = { vus: 50, duration: '30m' };
const BASE = 'https://baw.example.com', AUTH = { Authorization: 'Basic ' + __ENV.CRED };
export default function () {
let r = http.post(BASE + '/rest/bpm/wle/v1/system/login', JSON.stringify({ requested_lifetime: 7200 }), { headers: { ...AUTH, 'Content-Type': 'application/json' } });
const H = { headers: { ...AUTH, BPMCSRFToken: r.json('csrf_token') } };
r = http.put(BASE + '/rest/bpm/wle/v1/search/query?organization=byTask&run=true&size=20&condition=taskStatus%7CReceived&filterByCurrentUser=true', null, H);
check(r, { 'list 200': x => x.status === 200 }); const tasks = r.json('data.data') || []; if (!tasks.length) { sleep(5); return; }
const t = tasks[0].taskId; sleep(3); // think time
http.put(BASE + '/rest/bpm/wle/v1/task/' + t + '?action=assign&toMe=true&parts=none', null, H);
r = http.get(BASE + '/teamworks/process.lsw?zTaskId=' + t.split('.')[1], { headers: AUTH }); // the coach page: HTML, JS and its service calls
check(r, { 'coach 200': x => x.status === 200 }); sleep(20); // user works on the form
r = http.put(BASE + '/rest/bpm/wle/v1/task/' + t + '?action=finish&parts=none¶ms=' + encodeURIComponent(JSON.stringify({ decision: 'APPROVED' })), null, H);
check(r, { 'finish 200': x => x.status === 200 }); sleep(2);
}
// second scenario (own VUs) starts instances at the target rate:
// http.post(BASE + '/rest/bpm/wle/v1/process?action=start&bpdId=...&snapshotId=...&parts=none¶ms=' + encodeURIComponent(JSON.stringify(data)), null, H)What to measure and typical targets:
- Client side: p95 of task list (under 2 s), coach load (under 3 s), submit (under 2 s), instance start (under 1 s), error rate zero.
- Server side: JVM heap after GC and GC pauses, thread pool usage (WebContainer on WAS, default executor on Liberty), JDBC pool wait time (must stay near zero - the classic bottleneck), Event Manager backlog (timers and UCAs keeping up), database CPU and lock waits, BPMDB growth per instance (for retention sizing), and on CP4BA pod CPU / memory against requests and the horizontal autoscaler.
- Sources: WebSphere PMI (JDBC, thread pools, servlets) or Liberty's monitor feature scraped by Prometheus on CP4BA, plus instance throughput from the PDW or the Operations REST API.
Test design rules: warm up for 10 minutes before measuring (JIT, caches); use as many distinct users as real life (user caches and team resolution behave differently for 5 users than for 500); include timers, UCAs and integrations with realistic latency (stubs with delays); run at 100 %, 150 % and a multi-hour soak (memory leaks, database growth); and reset the environment (delete instances) between runs so results compare. Team filters, business data searches, large execution contexts and unindexed custom SQL are the usual findings.
References