k6 teardown rollback gap after schema changes under forced termination
0 reputation · 28 Nov 2020, 04:47 UTC
0 reputation · 28 Nov 2020, 04:47 UTC
k6's documented execution lifecycle includes a teardown() function that runs after all VUs finish. That makes teardown a natural place to drop temporary schema objects or restore a prior schema state when a load test creates database artifacts.
The uncertainty is what happens when the test process does not stop gracefully. Normal SIGINT/SIGTERM handling is documented to finish the current iteration and then run teardown, but an abrupt kill (SIGKILL) prevents k6 from receiving the signal. The documentation does not appear to guarantee teardown for every abnormal termination path, and behavior may differ in older k6 releases before v0.45.
For a test environment where schema changes must be rolled back safely, relying only on teardown leaves an unresolved design decision. Should rollback be idempotent and external to k6, or is there a supported lifecycle hook that covers forced termination?
34775 reputation · 28 Nov 2020, 07:52 UTC
Does k6 guarantee teardown execution after a graceful stop? – Yes. In all supported releases that include the teardown() hook (v0.45+ and back to v0.28), a SIGINT or SIGTERM causes k6 to finish the current iteration, wait for all VUs to finish, then invoke teardown() before exiting.
What happens when the process is killed abruptly? – A SIGKILL (or similar non‑interceptable signal) terminates the process immediately. k6 never receives the signal, so teardown() is not executed. This has been consistent since reliable signal handling was added.
How should schema rollback be structured when teardown may not run? – Implement the rollback as an independent, idempotent script that runs after the k6 process exits, regardless of exit status. Wrap the k6 invocation in a supervisor that waits for the process to finish and then triggers the cleanup.
cleanup.sh that drops temporary tables or restores a baseline snapshot. It should be safe to run multiple times and should check for the existence of the objects before attempting to drop them.#!/usr/bin/env bash
set -e
# Run k6 and capture its exit code
k6 run test.js
EXIT_CODE=$?
# Always run cleanup, regardless of exit code
./cleanup.sh
# Exit with the original k6 status
exit $EXIT_CODE
trap for graceful signals – The wrapper can also trap SIGINT/SIGTERM to allow early cleanup if the user hits Ctrl‑C while k6 is still running.
trap 'echo "Interrupted"; kill -s SIGTERM $k6_pid' INT TERM
teardown() writes to a file. Run with SIGINT, confirm the file is updated; run with SIGKILL, confirm the file is unchanged; finally run the wrapper, confirm cleanup.sh executes in both cases.import http from "k6/http";
export default function () { http.get("http://example.com"); }
export function teardown() { require("fs").writeFileSync("teardown.log", "done"); }
k6 run script.js, press Ctrl‑C after 5 s, then check teardown.log exists.kill -9 $(pgrep k6) and verify teardown.log is missing.cleanup.sh runs in both scenarios.Rely on teardown() only for non‑destructive or idempotent cleanup that can tolerate occasional omission. For destructive schema changes, always use an external, idempotent rollback that is invoked by a wrapper or orchestration tool after the k6 process exits. This guarantees cleanup even if the test is killed abruptly.
If you need to know the exact k6 version you are running, run k6 version. For older releases (
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.