Skip to content

Instantly share code, notes, and snippets.

@nickva
Created February 7, 2026 17:31
Show Gist options
  • Select an option

  • Save nickva/c6ed2bb9a883a6e4051ce7a2d94be244 to your computer and use it in GitHub Desktop.

Select an option

Save nickva/c6ed2bb9a883a6e4051ce7a2d94be244 to your computer and use it in GitHub Desktop.
couchdb k6 view query with constant arrival
//
// Examples:
// BENCH_RATE=500 BENCH_DURATION=20s BENCH_VIEW_LIMIT=16 k6 run ./$script.js
//
// config:set("log", "level", "warning").
//
import http from 'k6/http';
import encoding from 'k6/encoding';
import { sleep } from 'k6';
import { randomString } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
// Parameters, defaults or from the environment
// Note: environemnt variables are prefixed with "BENCH_"
//
const URL = env_str('URL', 'http://localhost:15984');
const USER = env_str('USER', 'adm');
const PASS = env_str('PASS', 'pass');
const DB = env_str('DB', 'db');
const DDOC = env_str('DDOC', 'ddoc')
const VIEW = env_str('VIEW', 'view')
const VIEW_LIMIT = env_num('VIEW_LIMIT', 1)
const DURATION = env_str('DURATION', '5m');
const RATE = env_num('RATE', 500);
const TAG = env_str('TAG', '');
const SCENARIOS = env_str('SCENARIOS', 'view_get');
const XHEADER = env_str('XHEADER', '');
// Derived params
const DB_URL = `${URL}/${DB}`;
const VIEW_URL = `${URL}/${DB}/_design/${DDOC}/_view/${VIEW}`
const INFO_URL = `${URL}/${DB}/_design/${DDOC}/_info`
const HEADERS = get_headers(XHEADER, USER, PASS);
const SETUP_PAR = {'headers': HEADERS, tags: {name: 'setup'}};
const VIEW_PAR = {'headers': HEADERS, tags: {name: 'view_get'}};
const SCENARIO_DEFAULTS = {
executor: 'constant-arrival-rate',
duration: DURATION,
timeUnit: '1s',
preAllocatedVUs: 1000,
maxVUs: 5000
};
// Callbacks & options. These are what k6 expects to call
export const options = {
scenarios: scenarios(),
discardResponseBodies: true,
setupTimeout: '60m',
// These are bogus, always passing thresholds just so we can
// see the individual tagged requests times in the summary
// but in principle these could be turned into a pass/fail test
thresholds: {
'http_req_duration{name:view_get}' : ['p(99)>=0']
}
};
export function setup() {
console.log(`
* tag: ${TAG}
* scanarios: ${SCENARIOS}
* url: ${URL}
* user: ${USER}
* ddoc: ${DDOC}
* view: ${VIEW}
* duration: ${DURATION}
\n`);
let res;
res = http.get(DB_URL, SETUP_PAR);
if (res.status != 200) {
throw new Error(`Could not find DB ${DB_URL} ${res.status}`);
}
res = http.get(INFO_URL, SETUP_PAR);
if (res.status != 200) {
throw new Error(`Could not find view at ${INFO_URL} ${res.status}`);
}
}
export function view_get () {
const skey = randomString(10, 'abcdef0123456789');
http.get(`${VIEW_URL}?start_key="${skey}"&limit=${VIEW_LIMIT}`, VIEW_PAR);
}
/// End of callback functions
// Helpers
function env_str(name, default_val) {
name = 'BENCH_' + name;
return __ENV[name] ? __ENV[name] : default_val;
}
function env_num(name, default_val) {
name = 'BENCH_' + name;
return __ENV[name] ? Number(__ENV[name]) : default_val;
}
function scenarios() {
let scenario_keys = SCENARIOS.split(',');
let scenarios_available = {
view_get : {...SCENARIO_DEFAULTS, ...{exec: 'view_get'}, ...{rate: RATE}}
};
return Object.fromEntries(scenario_keys.map(k => [k, scenarios_available[k]]));
}
function get_headers(xtra_header, user, pass) {
let b64 = encoding.b64encode(`${user}:${pass}`);
let xheader = parse_header(xtra_header);
return {
'authorization': `Basic ${b64}`,
'content-type':'application/json',
...xheader
}
};
function parse_header(header_str) {
let [name, ...rest] = header_str.split(":");
let val = rest.join(":");
return name ? {name : val} : {};
}
@nickva
Copy link
Author

nickva commented Feb 7, 2026

Run as:

BENCH_RATE=400 BENCH_DURATION=5m BENCH_VIEW_LIMIT=10 k6 run ./k6_couchdb_constant_arrival_view_query.js 

Views can be created with view_cycle.py

./view_cycle.py -u http://localhost:15984 -a adm:pass -n 1000000 -c0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment