Skip to main content

RFC-029: Load Testing Framework Evaluation and Strategy

Summary

Evaluation of Go load testing frameworks for Prism data access gateway. Analyzes custom tool (prism-loadtest) vs best-of-breed frameworks (ghz, k6, vegeta, fortio) and proposes a two-tier testing strategy: custom tool for pattern-level load testing + ghz for end-to-end gRPC integration testing.

Recommendation: Keep custom prism-loadtest tool and add ghz for gRPC integration testing.

Key Finding: Prism needs two types of load testing:

  1. Pattern-level: Tests pattern logic directly (current custom tool)
  2. Integration-level: Tests through Rust proxy via gRPC (needs ghz)

Motivation

Problem

Current load testing tool (cmd/prism-loadtest) is custom-built:

  • ✅ Production-ready (validated by MEMO-010)
  • ✅ Direct Pattern SDK integration
  • ✅ Custom metrics collection
  • ❌ Tests patterns directly (not through proxy)
  • ❌ No gRPC integration testing
  • ❌ Maintenance burden (custom code)

Question: Should we adopt a best-of-breed framework or keep the custom tool?

Goals

  1. Evaluate best-of-breed Go load testing frameworks
  2. Compare frameworks against Prism requirements
  3. Recommend load testing strategy for POC 1+
  4. Define testing scope (pattern-level vs integration-level)

Current State: Custom Load Testing Tool

Architecture

┌─────────────────────────────────────────────────────────────┐
│ prism-loadtest CLI (Custom Tool) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ register │ │ enumerate │ │ multicast │ │
│ │ command │ │ command │ │ command │ │
│ └──────┬───────┘ └──────┬───────┘ └───────┬───────┘ │
│ │ │ │ │
│ └──────────────────┴───────────────────┘ │
│ │ │
│ ┌─────────────▼──────────────┐ │
│ │ Coordinator (direct call) │ │
│ └─────────────┬──────────────┘ │
│ │ │
│ ┌──────────────────┴────────────────┐ │
│ │ │ │
│ ┌────▼─────┐ ┌─────▼──────┐ │
│ │ Redis │ │ NATS │ │
│ │ Backend │ │ Backend │ │
│ └──────────┘ └────────────┘ │
└─────────────────────────────────────────────────────────────┘

Key Characteristics:

  • Tests pattern logic directly (bypasses proxy)
  • Direct Coordinator instantiation
  • No gRPC overhead
  • Isolated backend testing (Redis + NATS)

Implementation Details

FeatureImplementationLOC
CLI FrameworkCobra~100
Rate Limitinggolang.org/x/time/rate~50
Metrics CollectionCustom histogram~150
Progress ReportingCustom ticker~50
Register CommandDirect Coordinator call~100
Enumerate CommandDirect Coordinator call~80
Multicast CommandDirect Coordinator call~120
Mixed WorkloadWeighted random~150
Total~800 LOC~800

Performance Validation (MEMO-010)

MetricTargetActualStatus
Rate Limiting100 req/sec101.81 req/sec✅ 1.81% error
Workload Mix50/30/2050.1/30.0/20.0✅ Precise
Thread SafetyNo data racesFixed with mutex✅ Safe
Register P95<10ms5ms✅ 2x faster
Enumerate P95<20ms500µs✅ 40x faster
Multicast P95<100ms100ms✅ On target

Verdict: Custom tool is production-ready

Strengths

  1. Direct Integration: Tests pattern logic without gRPC overhead
  2. Custom Metrics: Tailored to Prism patterns (multicast delivery stats)
  3. Proven: Validated by POC 4 (MEMO-010)
  4. Fast Iteration: No external dependencies
  5. Workload Flexibility: Mixed workloads with precise distribution

Weaknesses

  1. No gRPC Testing: Doesn't test through Rust proxy
  2. Maintenance Burden: ~800 LOC to maintain
  3. Not Best-of-Breed: Missing features like:
    • Advanced load profiles (ramp-up, spike, soak)
    • Distributed load generation (multiple clients)
    • Real-time dashboards
    • Standard output formats (JSON, CSV)

Framework Evaluation

Selection Criteria

CriterionWeightDescription
gRPC SupportHighCritical for Prism architecture
Custom MetricsHighNeed pattern-specific metrics (multicast delivery)
Learning CurveMediumTeam productivity
MaintenanceMediumLong-term support
IntegrationHighWorks with existing patterns
PerformanceMediumTool shouldn't bottleneck tests

Framework 1: ghz (gRPC Load Testing)

URL: https://github.com/bojand/ghz

Description: gRPC benchmarking and load testing tool written in Go.

Architecture

┌──────────────────────────────────────────────────────────┐
│ ghz CLI │
│ │
│ ┌────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Proto File │ │ Rate Config │ │ Load Profile │ │
│ └─────┬──────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └─────────────────┴──────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ gRPC Client (tonic) │ │
│ └───────────┬───────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ Rust Proxy :8980 │ │
│ └───────────┬───────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ Pattern (MemStore/ │ │
│ │ Redis/Kafka) │ │
│ └───────────────────────┘ │
└──────────────────────────────────────────────────────────┘

Features

FeatureSupportNotes
gRPC Support✅ NativeBuilt specifically for gRPC
Protocol Buffers✅ RequiredRequires .proto files
Rate Limiting✅ Built-inConstant, step, line profiles
Concurrency✅ Built-inConfigurable workers
Output Formats✅ JSON, CSV, HTMLStandard formats
Real-time Stats✅ Built-inProgress bar
Custom Metrics❌ LimitedStandard gRPC metrics only
Direct Integration❌ NoMust go through gRPC

Example Usage

# Basic gRPC load test
ghz --proto ./proto/interfaces/keyvalue_basic.proto \
--call prism.KeyValueBasicInterface.Set \
--insecure \
--total 6000 \
--concurrency 100 \
--rps 100 \
--duration 60s \
--data '{"namespace":"default","key":"test-key","value":"dGVzdC12YWx1ZQ=="}' \
localhost:8980

# Output:
# Summary:
# Count: 6000
# Total: 60.00 s
# Slowest: 15.23 ms
# Fastest: 0.45 ms
# Average: 2.31 ms
# Requests/sec: 100.00
#
# Response time histogram:
# 0.450 [1] |
# 1.928 [2341] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
# 3.406 [2892] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
# 4.884 [582] |∎∎∎∎∎∎∎
# 6.362 [145] |∎∎
# 7.840 [32] |
# 9.318 [5] |
# 10.796 [1] |
# 12.274 [0] |
# 13.752 [0] |
# 15.230 [1] |
#
# Status code distribution:
# [OK] 6000 responses

Pros

  • gRPC Native: Tests through actual Rust proxy (integration testing)
  • Production-Grade: Used by many companies
  • Standard Output: JSON, CSV, HTML reports
  • Load Profiles: Ramp-up, step, spike patterns
  • Minimal Code: Zero code for basic tests

Cons

  • No Direct Integration: Can't test pattern logic directly
  • Limited Custom Metrics: Can't track multicast delivery stats
  • Proto Dependency: Requires .proto files (manageable)
  • Less Flexible: Hard to implement mixed workloads

Score

CriterionScore (1-5)Reasoning
gRPC Support5Native gRPC support
Custom Metrics2Limited to standard gRPC metrics
Learning Curve4Simple CLI, easy to learn
Maintenance5External project, no code to maintain
Integration3Tests through proxy (good), not patterns (bad)
Performance5High-performance tool
Total24/30Strong for integration testing

Framework 2: k6

URL: https://k6.io/

Description: Modern load testing tool with Go runtime and JavaScript scripting.

Architecture

┌──────────────────────────────────────────────────────────┐
│ k6 (Go Runtime) │
│ │
│ ┌────────────────────────────────────────────────┐ │
│ │ JavaScript Test Script (user-written) │ │
│ │ │ │
│ │ export default function() { │ │
│ │ const client = new grpc.Client(); │ │
│ │ client.connect("localhost:8980"); │ │
│ │ client.invoke("Set", { key: "foo" }); │ │
│ │ } │ │
│ └────────────────────────┬───────────────────────┘ │
│ │ │
│ ┌────────────▼─────────────┐ │
│ │ k6 Go Runtime (goja) │ │
│ └────────────┬─────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────┐ │
│ │ Rust Proxy :8980 │ │
│ └────────────────────────┘ │
└──────────────────────────────────────────────────────────┘

Features

FeatureSupportNotes
gRPC Support✅ PluginVia k6-grpc extension
Protocol Buffers✅ RequiredRequires .proto reflection or files
Rate Limiting✅ Built-inVirtual users + iterations
Concurrency✅ Built-inVirtual user model
Output Formats✅ JSON, CSV, Cloudk6 Cloud integration
Real-time Stats✅ Built-inBeautiful terminal UI
Custom Metrics✅ GoodCustom metrics via JS
Direct Integration❌ NoJavaScript only

Example Usage

// loadtest.js
import grpc from 'k6/net/grpc';
import { check } from 'k6';

const client = new grpc.Client();
client.load(['proto'], 'keyvalue_basic.proto');

export default function () {
client.connect('localhost:8980', { plaintext: true });

const response = client.invoke('prism.KeyValueBasicInterface/Set', {
namespace: 'default',
key: 'test-key',
value: Buffer.from('test-value').toString('base64'),
});

check(response, {
'status is OK': (r) => r.status === grpc.StatusOK,
});

client.close();
}

export const options = {
vus: 100, // 100 virtual users
duration: '60s',
thresholds: {
'grpc_req_duration': ['p(95)&lt;10'], // P95 &lt; 10ms
},
};
# Run load test
k6 run loadtest.js

# Output:
# /\ |‾‾| /‾‾/ /‾‾/
# /\ / \ | |/ / / /
# / \/ \ | ( / ‾‾\
# / \ | |\ \ | (‾) |
# / __________ \ |__| \__\ \_____/ .io
#
# execution: local
# script: loadtest.js
# output: -
#
# scenarios: (100.00%) 1 scenario, 100 max VUs, 1m30s max duration
#
# ✓ status is OK
#
# grpc_req_duration.........: avg=2.31ms p(95)=4.5ms p(99)=8.2ms
# grpc_reqs.................: 6000 100.00/s
# vus.......................: 100 min=100 max=100

Pros

  • Modern UX: Beautiful terminal UI
  • Custom Metrics: JavaScript flexibility
  • Load Profiles: Sophisticated VU ramping
  • Cloud Integration: k6 Cloud for distributed testing
  • Ecosystem: Large community, extensions

Cons

  • JavaScript Required: Team must learn JS for load tests
  • gRPC Via Plugin: Not native gRPC support
  • Complexity: Overkill for simple tests
  • No Direct Integration: Can't test patterns directly

Score

CriterionScore (1-5)Reasoning
gRPC Support3Via plugin, not native
Custom Metrics4Good JS flexibility
Learning Curve2Requires JavaScript knowledge
Maintenance5External project
Integration2Must learn k6 + JS ecosystem
Performance4High-performance (Go runtime)
Total20/30Powerful but complex

Framework 3: vegeta (HTTP Library)

URL: https://github.com/tsenart/vegeta

Description: HTTP load testing library and CLI tool.

Features

FeatureSupportNotes
gRPC Support❌ NoHTTP only
HTTP/2✅ YesCan test gRPC-Web
Rate Limiting✅ Built-inConstant rate
Concurrency✅ Built-inWorker pool
Output Formats✅ JSON, CSV, binaryStandard formats
Library Mode✅ YesCan embed in Go code
Custom Metrics✅ GoodGo library flexibility

Pros

  • Library: Can embed in custom tools
  • Mature: Well-tested, stable
  • Go Native: Easy integration

Cons

  • No gRPC: HTTP only (dealbreaker for Prism)

Score

CriterionScore (1-5)Reasoning
gRPC Support0No gRPC support
TotalDisqualifiedNo gRPC = not viable

Framework 4: fortio (Istio's Tool)

URL: https://github.com/fortio/fortio

Description: Load testing tool from Istio project (HTTP + gRPC).

Features

FeatureSupportNotes
gRPC Support✅ YesNative gRPC support
HTTP Support✅ YesAlso supports HTTP/HTTP2
Rate Limiting✅ Built-inQPS control
Concurrency✅ Built-inConfigurable connections
Output Formats✅ JSON, HTMLIncludes web UI
Web UI✅ Built-inReal-time dashboard
Custom Metrics❌ LimitedStandard metrics only

Example Usage

# gRPC load test
fortio load \
-grpc \
-n 6000 \
-c 100 \
-qps 100 \
-t 60s \
localhost:8980

# Output similar to ghz

Pros

  • gRPC + HTTP: Dual protocol support
  • Web UI: Real-time dashboard
  • Istio Integration: If we use Istio later

Cons

  • Limited Flexibility: Can't do complex workflows
  • Basic Metrics: Standard metrics only
  • Less Popular: Smaller community than ghz

Score

CriterionScore (1-5)Reasoning
gRPC Support5Native gRPC support
Custom Metrics2Limited to standard metrics
Learning Curve4Simple CLI
Maintenance4Istio project (stable)
Integration3Tests through proxy only
Performance4Good performance
Total22/30Solid alternative to ghz

Framework 5: hey / bombardier (HTTP Tools)

Description: Simple HTTP benchmarking tools.

Verdict: ❌ Disqualified - No gRPC support


Framework Comparison Matrix

FrameworkgRPCCustom MetricsLearning CurveMaintenanceIntegrationPerformanceTotal
ghz52453524/30
k634252420/30
fortio52443422/30
vegeta0-----Disqualified
hey/bombardier0-----Disqualified
Custom Tool05525522/30

Key Observations:

  1. ghz scores highest for integration testing (24/30)
  2. Custom tool excellent for pattern-level testing (22/30)
  3. k6 powerful but complex (20/30)
  4. fortio solid alternative to ghz (22/30)

Testing Strategy: Two-Tier Approach

Insight: Two Types of Load Testing

Prism needs two distinct types of load testing:

1. Pattern-Level Load Testing (Unit Load Testing)

Goal: Test pattern logic in isolation

Tool: Custom prism-loadtest

Architecture:

prism-loadtest → Coordinator → Redis/NATS

Benefits:

  • ✅ No proxy overhead (fastest possible)
  • ✅ Custom metrics (multicast delivery stats)
  • ✅ Direct debugging
  • ✅ Isolated testing

Use Cases:

  • Pattern development (POC 1-4)
  • Backend benchmarking (Redis vs SQLite)
  • Algorithm optimization (TTL cleanup, fan-out)

2. Integration-Level Load Testing (End-to-End)

Goal: Test through Rust proxy via gRPC

Tool: ghz

Architecture:

ghz → Rust Proxy (gRPC) → Pattern (gRPC) → Redis/NATS

Benefits:

  • ✅ Tests real production path
  • ✅ Includes gRPC overhead
  • ✅ Validates proxy performance
  • ✅ Catches serialization issues

Use Cases:

  • Integration testing (POC 1+)
  • Proxy performance validation
  • End-to-end latency measurement
  • Production load simulation
┌─────────────────────────────────────────────────────────────────┐
│ Load Testing Strategy │
│ │
│ ┌───────────────────────┐ ┌──────────────────────┐ │
│ │ Pattern-Level Tests │ │ Integration Tests │ │
│ │ (prism-loadtest) │ │ (ghz) │ │
│ └───────────┬───────────┘ └──────────┬───────────┘ │
│ │ │ │
│ │ │ │
│ ▼ ▼ │
│ ┌───────────────────────┐ ┌──────────────────────┐ │
│ │ Coordinator (direct) │ │ Rust Proxy (gRPC) │ │
│ └───────────┬───────────┘ └──────────┬───────────┘ │
│ │ │ │
│ └─────────────┬───────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────┐ │
│ │ Redis + NATS Backends │ │
│ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

Phase 1: POC 1 (Current State)

Keep Custom Tool (prism-loadtest)

Rationale:

  • Already production-ready (MEMO-010)
  • Pattern-level testing sufficient for POC 1
  • No proxy implementation yet

Actions:

  • Continue using prism-loadtest
  • Add advanced load profiles (ramp-up, spike)
  • Add JSON output format

Phase 2: POC 2+ (Add Integration Testing)

Add ghz for Integration Testing

Rationale:

  • Rust proxy will be ready
  • Need end-to-end testing
  • ghz scores highest for integration (24/30)

Actions:

  • Install ghz
  • Create ghz test scenarios for each pattern
  • Integrate into CI/CD
  • Compare results (pattern-level vs integration)

Example ghz Test Suite:

# tests/load/ghz/keyvalue.sh
#!/bin/bash

# Test MemStore pattern via proxy
ghz --proto proto/interfaces/keyvalue_basic.proto \
--call prism.KeyValueBasicInterface.Set \
--insecure \
--rps 100 \
--duration 60s \
--data '{"namespace":"default","key":"test-{{.RequestNumber}}","value":"dGVzdC12YWx1ZQ=="}' \
--output json \
--output-path results/memstore-set.json \
localhost:8980

# Test Redis pattern via proxy
ghz --proto proto/interfaces/keyvalue_basic.proto \
--call prism.KeyValueBasicInterface.Get \
--insecure \
--rps 100 \
--duration 60s \
--data '{"namespace":"default","key":"test-{{.RequestNumber}}"}' \
--output json \
--output-path results/redis-get.json \
localhost:8981

Phase 3: Future (Optional Enhancements)

Consider k6 for Advanced Scenarios

⚠️ Use Cases:

  • Multi-protocol testing (gRPC + HTTP + WebSocket)
  • Complex user journeys (multi-step workflows)
  • Cloud-scale distributed load testing

Decision Criteria:

  • If we need distributed load testing → Adopt k6
  • If simple gRPC testing sufficient → Stick with ghz

Implementation Plan

Week 1: Enhance Custom Tool

Tasks:

  1. Add ramp-up load profile

    // cmd/prism-loadtest/cmd/root.go
    rootCmd.PersistentFlags().String("profile", "constant", "Load profile: constant, ramp-up, spike")
    rootCmd.PersistentFlags().Int("ramp-duration", 30, "Ramp-up duration (seconds)")
    rootCmd.PersistentFlags().Int("max-rate", 1000, "Max rate for ramp-up (req/sec)")
  2. Add JSON output format

    // cmd/prism-loadtest/cmd/output.go
    type JSONReport struct {
    Duration string `json:"duration"`
    TotalRequests int64 `json:"total_requests"`
    Successful int64 `json:"successful"`
    Failed int64 `json:"failed"`
    Throughput float64 `json:"throughput"`
    LatencyMin string `json:"latency_min"`
    LatencyMax string `json:"latency_max"`
    LatencyAvg string `json:"latency_avg"`
    LatencyP50 string `json:"latency_p50"`
    LatencyP95 string `json:"latency_p95"`
    LatencyP99 string `json:"latency_p99"`
    }
  3. Add spike load profile

    # 0-30s: 100 req/sec
    # 30-35s: 1000 req/sec (spike)
    # 35-60s: 100 req/sec
    ./prism-loadtest mixed --profile spike --spike-duration 5s --spike-rate 1000 -r 100 -d 60s

Estimated Effort: 2 days

Week 2: Add ghz Integration Testing

Tasks:

  1. Install ghz

    go install github.com/bojand/ghz/cmd/ghz@latest
  2. Create ghz test suite

    mkdir -p tests/load/ghz
    # Create test scripts for each pattern
  3. Add to CI/CD

    # .github/workflows/load-test.yml
    - name: Run integration load tests
    run: |
    # Start proxy
    cd proxy && cargo run --release &
    PROXY_PID=$!

    # Wait for proxy
    sleep 5

    # Run ghz tests
    ghz --proto proto/interfaces/keyvalue_basic.proto \
    --call prism.KeyValueBasicInterface.Set \
    --insecure \
    --rps 100 \
    --duration 30s \
    --data '{"namespace":"default","key":"test-key","value":"dGVzdC12YWx1ZQ=="}' \
    localhost:8980

    # Stop proxy
    kill $PROXY_PID
  4. Compare results

    # Pattern-level (no gRPC overhead)
    ./prism-loadtest register -r 100 -d 60s
    # Expected: P95 = 5ms

    # Integration-level (with gRPC overhead)
    ghz --proto proto/interfaces/keyvalue_basic.proto \
    --call prism.KeyValueBasicInterface.Set \
    --rps 100 \
    --duration 60s \
    localhost:8980
    # Expected: P95 = 8-10ms (gRPC adds ~3-5ms)

Estimated Effort: 3 days

Decision Matrix

ScenarioToolReasoning
Pattern Developmentprism-loadtestDirect integration, custom metrics
Backend Benchmarkingprism-loadtestNo proxy overhead
Integration TestingghzTests through proxy
CI/CD RegressionghzEnd-to-end validation
Production ValidationghzReal production path
Algorithm Optimizationprism-loadtestIsolated, fastest feedback
Complex Workflowsk6 (future)Multi-step scenarios

Benefits

Two-Tier Strategy

  1. Best of Both Worlds:

    • Pattern-level: Fast iteration, custom metrics
    • Integration-level: Production accuracy
  2. Minimal Code Changes:

    • Keep existing prism-loadtest (validated)
    • Add ghz (zero code, just scripts)
  3. Comprehensive Coverage:

    • Unit load testing: Pattern logic
    • Integration load testing: End-to-end
  4. Clear Separation:

    • Developers: Use prism-loadtest for pattern work
    • QA/DevOps: Use ghz for integration/production validation

Cost-Benefit Analysis

ApproachCode MaintenanceFeaturesCoverageScore
Custom OnlyHigh (~800 LOC)Custom metrics ✅Pattern-level only ❌2/3
ghz OnlyNoneStandard metrics ❌Integration-level only ❌1/3
Two-TierMedium (~800 LOC)Custom metrics ✅Both levels ✅3/3
k6 OnlyNoneAdvanced ✅Integration-level only ❌2/3

Winner: Two-Tier Strategy (3/3)

Risks and Mitigations

Risk 1: Maintaining Two Tools

Risk: Overhead of maintaining prism-loadtest + ghz scripts

Mitigation:

  • prism-loadtest: Only ~800 LOC, well-tested
  • ghz: No code to maintain (just shell scripts)
  • Clear separation: developers use custom, QA uses ghz

Risk 2: Results Divergence

Risk: Pattern-level vs integration-level results differ significantly

Mitigation:

  • Expected: gRPC adds ~3-5ms latency (acceptable)
  • Document baseline overhead
  • Alert if divergence > 10ms (indicates proxy issue)

Risk 3: Tool Proliferation

Risk: Team confused about which tool to use

Mitigation:

  • Clear documentation (this RFC)
  • Decision matrix (see above)
  • CI/CD examples

Alternatives Considered

Alternative 1: ghz Only

Pros:

  • No custom code maintenance
  • Standard tool

Cons:

  • ❌ Can't test patterns directly
  • ❌ No custom metrics (multicast delivery)
  • ❌ Slower iteration (must start proxy)

Decision: Rejected - need pattern-level testing

Alternative 2: k6 Only

Pros:

  • Modern, powerful
  • Large ecosystem

Cons:

  • ❌ Requires JavaScript
  • ❌ Overkill for simple tests
  • ❌ No direct pattern integration

Decision: Rejected - too complex for current needs

Alternative 3: Custom Only + vegeta Library

Idea: Embed vegeta library in prism-loadtest for HTTP testing

Pros:

  • Single tool

Cons:

  • ❌ vegeta doesn't support gRPC
  • ❌ More maintenance burden

Decision: Rejected - vegeta doesn't support gRPC

Success Metrics

MetricTargetMeasurement
Tool Adoption100% team uses toolsSurvey after POC 2
Pattern-Level CoverageAll patterns have load testsTest inventory
Integration CoverageAll gRPC endpoints testedghz test suite
Performance Baseline<5ms P95 pattern-levelprism-loadtest results
Performance Integration<10ms P95 end-to-endghz results
CI/CD IntegrationLoad tests in CI pipelineGitHub Actions

Next Steps

Immediate (POC 1)

  1. Enhance prism-loadtest:

    • Add ramp-up profile
    • Add JSON output
    • Add spike profile
  2. Document usage:

    • Update README with examples
    • Create decision matrix doc

Short-Term (POC 2)

  1. Install ghz:

    • Add to Dockerfile
    • Create ghz test suite
  2. CI/CD Integration:

    • Add ghz tests to GitHub Actions
    • Set up performance regression alerts

Long-Term (POC 5+)

  1. Evaluate k6 (if needed):
    • Assess need for distributed load testing
    • If yes: Create k6 test suite

Conclusion

Recommendation: Adopt two-tier load testing strategy:

  1. Keep prism-loadtest for pattern-level testing

    • Validated by MEMO-010
    • Custom metrics
    • Fast iteration
  2. Add ghz for integration testing

    • Tests through Rust proxy
    • Standard gRPC tool
    • Zero code maintenance

This strategy provides:

  • ✅ Comprehensive coverage (pattern + integration)
  • ✅ Minimal maintenance (800 LOC + scripts)
  • ✅ Clear separation (dev vs QA tools)
  • ✅ Best-of-breed solutions for each use case

Action: Proceed with Phase 1 (enhance custom tool) and Phase 2 (add ghz).

Revision History

  • 2025-10-11: Initial evaluation of Go load testing frameworks and recommendation for two-tier strategy