Performance testing suite for FerrisKey and Keycloak using k6.
- Token Endpoint - OAuth2 client credentials and password grants
- JWKS Endpoint - JSON Web Key Set retrieval
- Userinfo Endpoint - OpenID Connect userinfo
- Mixed Workload - Realistic traffic patterns
- Multi-Provider - Works with FerrisKey and Keycloak
git clone https://github.com/ferriskey/ferriskey-perf-tester.git
cd ferriskey-perf-tester
# Install dependencies
uv sync
# Create minimal config
cp .env.example .env# IAM provider: "ferriskey" or "keycloak"
IAM_PROVIDER=keycloak
# Server URL
BASE_URL=http://localhost:8080
# Admin credentials
ADMIN_USERNAME=admin
ADMIN_PASSWORD=adminThat's it! The seeder will auto-generate CLIENT_ID and retrieve CLIENT_SECRET from the server.
uv run python scripts/seed_test_data.pyThis will:
- Create a performance test realm
- Create a test client (auto-generated ID)
- Retrieve the client secret from the server
- Create test users
- Generate
.env.testwith all k6 configuration
# Use the generated .env.test
set -a && source .env.test && set +a
# Run tests
k6 run k6/scenarios/token_client_credentials.js
k6 run k6/scenarios/token_password.js
k6 run k6/scenarios/jwks.js
k6 run k6/scenarios/userinfo.js
k6 run k6/scenarios/mixed_workload.js
# With custom VUs and duration
k6 run --env VUS=100 --env DURATION=5m k6/scenarios/mixed_workload.jsuv run python scripts/cleanup_test_data.py # FerrisKey
uv run python scripts/cleanup_test_data_keycloak.py # Keycloakferriskey-perf-tester/
├── k6/
│ ├── scenarios/ # Test scenarios
│ │ ├── token_client_credentials.js
│ │ ├── token_password.js
│ │ ├── jwks.js
│ │ ├── userinfo.js
│ │ └── mixed_workload.js
│ └── lib/ # Shared libraries
│ ├── config.js
│ ├── auth.js
│ └── data.js
├── scripts/
│ ├── seed_test_data.py # Unified seeder (uses IAM_PROVIDER)
│ ├── cleanup_test_data.py
│ ├── cleanup_test_data_keycloak.py
│ └── lib/ # Provider implementations
│ ├── base_provider.py
│ ├── ferriskey_provider.py
│ └── keycloak_provider.py
├── .env.example # Minimal configuration template
├── .env.test # Generated k6 configuration (after seeding)
└── README.md
| Variable | Description | Default |
|---|---|---|
IAM_PROVIDER |
ferriskey or keycloak |
ferriskey |
BASE_URL |
Server URL | localhost:3333 (FK) / localhost:8080 (KC) |
ADMIN_USERNAME |
Admin username | admin |
ADMIN_PASSWORD |
Admin password | admin |
PERF_REALM |
Test realm name | perf-realm (FK) / perf (KC) |
USER_COUNT |
Number of test users | 50 |
USER_PASSWORD |
Test user password | perf-password |
After seeding, .env.test contains everything k6 needs:
BASE_URL=http://localhost:8080
REALM=perf
CLIENT_ID=perf-client-abc123 # Auto-generated
CLIENT_SECRET=xK9mLp2n... # Retrieved from server
TEST_USERNAME=perf-user-001
TEST_PASSWORD=perf-password
VUS=50
DURATION=5m| Scenario | Description | p95 Threshold |
|---|---|---|
token_client_credentials.js |
OAuth2 client credentials grant | < 100ms |
token_password.js |
OAuth2 password grant | < 150ms |
jwks.js |
JWKS endpoint | < 20ms |
userinfo.js |
OpenID Connect userinfo | < 50ms |
mixed_workload.js |
Weighted mix (40% CC, 20% PW, 30% UI, 10% JWKS) | varies |
- name: Seed test data
run: uv run python scripts/seed_test_data.py
env:
IAM_PROVIDER: keycloak
BASE_URL: ${{ secrets.KEYCLOAK_URL }}
ADMIN_USERNAME: ${{ secrets.ADMIN_USERNAME }}
ADMIN_PASSWORD: ${{ secrets.ADMIN_PASSWORD }}
- name: Run performance tests
run: |
set -a && source .env.test && set +a
k6 run --out json=results.json k6/scenarios/mixed_workload.js- Check server is running at
BASE_URL - Verify admin credentials
- For Keycloak, ensure
ADMIN_REALM=master
Check the BASE_URL in your .env matches where your IAM server is running.
Make sure to source .env.test before running k6:
set -a && source .env.test && set +a && k6 run ...MIT License - see LICENSE