Run k6 Load Tests Against Countly

This guide shows you how to run k6 load tests against a Countly server using the bundled load testing suite. The suite includes 5 named scenarios covering script validation, sustained data ingestion, and query load testing. All scenarios live in a single load_test.js file driven by environment variables.

Test against a non-production server

Some scenarios push thousands of requests per second and millions of synthetic users into the target Countly server. Always validate with a single-iteration scenario first on a staging environment. Only run sustained scenarios against a server you control end to end.

Prerequisites

Before you begin, confirm that:

  • You have k6 installed locally, or you can run it through Docker.
  • You have a Countly server URL and an application key (APP_KEY) to test against. The script has a hardcoded default server and app key for internal use; override both for any other deployment.
  • For query scenarios (query_soak, query_single), you also need an API key (API_KEY_QUERY) and application ID (APP_ID_QUERY) with access to the Drill endpoint.

Installing k6

Pick the installation method that matches your platform:

macOS

brew install k6

Linux (Debian or Ubuntu)

sudo gpg -k
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg \
  --keyserver hkp://keyserver.ubuntu.com:80 \
  --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69

echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" \
  | sudo tee /etc/apt/sources.list.d/k6.list

sudo apt-get update
sudo apt-get install k6

Linux (Fedora or CentOS)

sudo dnf install https://dl.k6.io/rpm/repo.rpm
sudo dnf install k6

Windows

choco install k6
# or
winget install k6 --source winget

Docker

docker pull grafana/k6
# Browser-enabled image
docker pull grafana/k6:master-with-browser

Verify the install:

k6 version

Running Your First Test

The default scenario is single. It sends one session-init request and confirms the script and server connection are working:

k6 run --env COUNTLY_SERVER=https://your-server.com \
       --env APP_KEY=your_app_key \
       load_test.js

To run a specific scenario, pass its name via SCENARIO:

k6 run --env SCENARIO=data_generation_soak \
       --env COUNTLY_SERVER=https://your-server.com \
       --env APP_KEY=your_app_key \
       load_test.js

Environment variables

SCENARIO defaults to single when omitted. COUNTLY_SERVER and APP_KEY have hardcoded internal defaults; always override them when testing a different deployment. Query scenarios additionally require API_KEY_QUERY and APP_ID_QUERY.

Choosing the Right Scenario

The 5 bundled scenarios cover three test functions. Pick the one that matches the question you are trying to answer:

ScenarioProfileUse Case
single1 VU, 1 iterationScript and connection validation (sends one begin_session request)
data_generation_single1 VU, 1 iterationSingle data-generation run for validating the full SDK payload pipeline
query_single1 VU, 1 iterationSingle Drill query run for validating query connectivity and auth
data_generation_soak10 req / 1 s, 600 sSustained SDK data ingestion — sessions, events, views, crashes, and user merges
query_soak10 req / 1 s, 600 sSustained Drill query load across 13 query types (equality, OR, AND, range, etc.)

Change the configuration profile for the selected scenarios to match your servers capabilities.

Long scenarios block your terminal

Soak scenarios run for 10 minutes plus a 5-minute graceful stop. Run them in a long-lived session (tmux, screen, or a dedicated VM) and confirm that your shell will not disconnect mid-test. Output to a log file with k6 run … 2>&1 | tee k6-soak.log.

Common Examples

Sustained Data Ingestion

k6 run --env SCENARIO=data_generation_soak \
       --env COUNTLY_SERVER=https://test.countly.com \
       --env APP_KEY=your_app_key \
       load_test.js

Sustained Query Load

k6 run --env SCENARIO=query_soak \
       --env COUNTLY_SERVER=https://test.countly.com \
       --env API_KEY_QUERY=your_api_key \
       --env APP_ID_QUERY=your_app_id \
       load_test.js

With Prometheus Remote Write

k6 run --env SCENARIO=data_generation_soak \
       --env COUNTLY_SERVER=https://test.countly.com \
       --env APP_KEY=your_app_key \
       --out experimental-prometheus-rw \
       load_test.js

Running in Docker

docker run --rm -v $(pwd):/k6 \
  -e COUNTLY_SERVER=https://your-server.com \
  -e APP_KEY=your_app_key \
  -e SCENARIO=data_generation_soak \
  grafana/k6 run /k6/load_test.js

Sending Results to Prometheus

k6 writes summary statistics to stdout by default. To send live metrics to Prometheus for visualization in Grafana, build a custom k6 binary with the Prometheus remote write extension:

go install go.k6.io/xk6/cmd/xk6@latest
xk6 build --with github.com/grafana/xk6-output-prometheus-remote

Then point the build at your Prometheus remote write endpoint and run with the experimental output:

export K6_PROMETHEUS_RW_SERVER_URL=http://localhost:9090/api/v1/write
export K6_PROMETHEUS_RW_TREND_STATS=p(50),p(90),p(95),p(99),max,min

./k6 run --out experimental-prometheus-rw \
       --env SCENARIO=data_generation_soak \
       --env COUNTLY_SERVER=https://your-server.com \
       --env APP_KEY=your_app_key \
       load_test.js

In Grafana, import dashboard 19665 (k6 Prometheus Dashboard) or 18595 (k6 Load Testing Results) for prebuilt visualizations.

Custom Metrics Tracked by the Suite

In addition to standard k6 metrics, the suite tracks Countly-specific business metrics:

  • session_init_count — session initialization attempts
  • events_count — total events sent
  • merges_count — user merge operations
  • session_end_count — session end events
  • Response time trends per query type (Query_01 through Query_15)
  • Per-operation success rate

These appear alongside http_req_* metrics in the standard k6 output and in any Prometheus remote write target.

Common Issues and Gotchas

Connection refused or timeouts under load
Confirm COUNTLY_SERVER is reachable from the host running k6, that APP_KEY is valid, and that no firewall or rate limiter sits between k6 and the server. Run single first to isolate connection issues from load issues.
Query scenarios return 401 or empty results
The query_soak and query_single scenarios require API_KEY_QUERY and APP_ID_QUERY in addition to APP_KEY. The API key must have access to the Drill endpoint. Run query_single first to confirm credentials before starting a sustained run.
Local CPU is the bottleneck before the server is
High-VU scenarios can saturate one machine's network and CPU before they stress a Countly cluster. Watch local CPU during a single-iteration run to confirm the bottleneck before drawing conclusions about the server. Run k6 inside a beefier VM or distribute across multiple workers for sustained high-load tests.
Dashboard shows no k6 data even though the run is in progress
Confirm K6_PROMETHEUS_RW_SERVER_URL is set and points at the right Prometheus instance. Confirm the k6 binary was built with the Prometheus remote write extension (a stock k6 install does not include it). Confirm the imported Grafana dashboard targets the same Prometheus data source.
Soak test stops mid-run
The session running k6 disconnected. Always run soak scenarios inside tmux or screen, on a dedicated host, or in a Kubernetes Job that persists across SSH sessions. 
Was this page helpful?
Reach out to us for any other questions.
Helpful?

Looking For More Help?