Performance Testing
Purpose
Performance Testing validates the robustness, responsiveness, and scalability of blockchain API endpoints under sustained load. This subtopic addresses the need to benchmark and analyze API throughput and latency when handling high request volumes, which is crucial for ensuring the ShapeShift Unchained platform maintains reliable service levels during peak usage.
Within the parent topic of Developer Tooling, Performance Testing provides a targeted means to simulate realistic traffic patterns against blockchain API servers, helping identify bottlenecks, measure system capacity, and validate improvements without impacting production environments.
Functionality
Performance Testing is implemented through load testing scripts using the [k6](https://k6.io/) tool, which executes HTTP requests against specific blockchain API endpoints with controlled concurrency and arrival rates. Key workflows and features include:
Scenario Configuration: Each load test script defines one or more scenarios specifying the request rate (
rate), virtual users (preAllocatedVUs), maximum users (maxVUs), and test duration (duration). This enables simulation of constant high-throughput traffic patterns.Targeted API Calls: Tests focus on critical REST endpoints such as account information and unspent transaction outputs (UTXOs) for Bitcoin, or account balances for Ethereum. The scripts cycle through a predefined list of addresses or extended public keys (xpubs) to mimic diverse client requests.
Thresholds and Metrics: The scripts specify performance thresholds, e.g., 95th percentile request duration under 800ms, and failure rates below 1%. These thresholds trigger alerts if violated, indicating degraded performance.
Result Summarization: After test completion, k6 generates JSON summaries containing detailed metrics such as average latency, percentiles, request counts, and error rates. These are saved to output files for further analysis.
Request Cycling Logic: Requests are distributed over a large dataset of addresses using modulo arithmetic on iteration counts, ensuring even load distribution and realistic address diversity.
Example: Ethereum Account Load Test
The Ethereum test script (`k6/ethereum/ethereum_test.js`) runs a 5-minute scenario sending 1000 requests per second distributed among 100+ Ethereum addresses:
export default function () {
http.get(`https://api.ethereum.shapeshift.com/api/v1/account/${addresses[exec.scenario.iterationInTest % addresses.length]}`)
}
The `options` block configures the constant-arrival-rate executor and thresholds for latency and failure rate.
Example: Bitcoin Account and UTXOs Load Test
The Bitcoin test script (`k6/bitcoin/bitcoin_test.js`) defines two scenarios simultaneously:
account: Requests for account details using a list of xpubs.utxos: Requests for UTXO data for the same xpubs.
Both scenarios run for 5 minutes at 1000 requests per second each, with thresholds enforcing 95th percentile latency below 800ms.
export function account() {
http.get(`https://api.bitcoin.shapeshift.com/api/v1/account/${xpubs[exec.scenario.iterationInTest % xpubs.length]}`)
}
export function utxos() {
http.get(`https://api.bitcoin.shapeshift.com/api/v1/account/${xpubs[exec.scenario.iterationInTest % xpubs.length]}/utxos`)
}
Integration
Performance Testing complements the Developer Tooling suite by providing quantitative feedback on the API layer's capacity and responsiveness, which is essential during development and before production deployment. It integrates with other subtopics as follows:
Docker Compose Environments: Tests can be run against local or staging environments spun up using Docker Compose, enabling developers to validate performance improvements in isolated setups.
Unified API Layer: Since the load tests target standardized REST endpoints exposed by the unified API, improvements or regressions detected by these tests reflect changes in the core API logic or underlying blockchain services.
Monitoring and Alerting: Performance test results can guide adjustments in Prometheus alert thresholds or Grafana dashboard focus, linking load test metrics with real-time observability.
This subtopic introduces the use of scenario-based, constant-arrival-rate load testing with address cycling and detailed thresholding, which is not covered in the broader parent topic or sibling subtopics.
Diagram
flowchart TD
Start[Test Start] --> Configure[Configure k6 Scenario]
Configure --> Loop[Iterate Through Addresses]
Loop --> SendRequest[Send HTTP GET Request]
SendRequest --> CollectMetrics[Collect Response & Metrics]
CollectMetrics --> CheckThresholds{Thresholds Met?}
CheckThresholds -->|Yes| Continue[Continue Test]
CheckThresholds -->|No| Alert[Log Threshold Violation]
Continue --> Loop
Loop --> End[Test Duration Reached?]
End -->|No| Loop
End -->|Yes| Summarize[Generate Summary Report]
Summarize --> Finish[Test End]
This flowchart captures the core load testing process: configuring scenarios, cycling through test addresses, sending requests, collecting and evaluating metrics against thresholds, and producing summary reports at test completion.