Complete 6 Sprint 1 stories for Epic 1 web migration infrastructure. Portfolio Collection: - Add 7 fields: title, slug, url, image, description, websiteType, tags - Configure R2 storage and authenticated access control Categories Collection: - Add nameEn, order, textColor, backgroundColor fields - Add color picker UI configuration Posts Collection: - Add excerpt with 200 char limit and ogImage for social sharing - Add showInFooter checkbox and status select (draft/review/published) Role-Based Access Control: - Add role field to Users collection (admin/editor) - Create adminOnly and authenticated access functions - Apply access rules to Portfolio, Categories, Posts, Users collections Audit Logging System (NFR9): - Create Audit collection with timestamps for 90-day retention - Add auditLogger utility for login/logout/content change tracking - Add auditChange and auditGlobalChange hooks to all collections and globals - Add cleanupAuditLogs job with 90-day retention policy Load Testing Framework (NFR4): - Add k6 load testing with 3 scripts: public-browsing, admin-operations, api-performance - Configure targets: p95 < 500ms, error rate < 1%, 100 concurrent users - Add verification script and comprehensive documentation Other Changes: - Remove unused Form blocks - Add Header/Footer audit hooks - Regenerate Payload TypeScript types
K6 Load Testing Framework
Overview
This directory contains load testing scripts for the Enchun CMS backend using k6. The tests are designed to validate the non-functional requirement NFR4:
- Target: p95 response time < 500ms
- Error rate: < 1%
- Concurrent users: 100
Prerequisites
-
Install k6:
# macOS brew install k6 # Linux sudo apt-get install k6 # Windows (using Chocolatey) choco install k6 -
Set up environment:
cp .env.example .env.k6 # Edit .env.k6 with your test environment credentials
Test Scripts
1. Public Browsing Test (public-browsing.js)
Simulates 100 concurrent users browsing public pages:
- Homepage
- About page
- Solutions page
- Portfolio list
- Blog list
- Contact page
Run:
k6 run --env BASE_URL=http://localhost:3000 tests/k6/public-browsing.js
Expected Results:
- p95 response time < 500ms
- Error rate < 1%
- 100 concurrent users sustained for 2 minutes
2. Admin Operations Test (admin-operations.js)
Simulates 20 concurrent admin users performing:
- Login
- List pages/posts
- Create/edit content
- Delete content
Run:
k6 run --env BASE_URL=http://localhost:3000 \
--env ADMIN_EMAIL=admin@example.com \
--env ADMIN_PASSWORD=password123 \
tests/k6/admin-operations.js
Expected Results:
- p95 response time < 500ms
- Error rate < 1%
- 20 concurrent users sustained for 3 minutes
3. API Performance Test (api-performance.js)
Tests specific API endpoints:
- GraphQL API queries
- REST API endpoints
- Global API endpoint
Run:
k6 run --env BASE_URL=http://localhost:3000 tests/k6/api-performance.js
Expected Results:
- p95 response time < 300ms (faster for API)
- Error rate < 0.5%
- Throughput > 100 requests/second
Configuration
Environment Variables
| Variable | Description | Default | Required |
|---|---|---|---|
BASE_URL |
Target server URL | http://localhost:3000 |
Yes |
ADMIN_EMAIL |
Admin user email | - | For admin tests |
ADMIN_PASSWORD |
Admin user password | - | For admin tests |
VUS |
Number of virtual users | Varies per test | No |
DURATION |
Test duration | Varies per test | No |
Load Profiles
Each test uses different load profiles:
| Test | Virtual Users | Duration | Ramp Up |
|---|---|---|---|
| Public Browsing | 100 | 2m | 30s |
| Admin Operations | 20 | 3m | 30s |
| API Performance | 50 | 5m | 1m |
Running Tests
Run Single Test
# Basic run
k6 run tests/k6/public-browsing.js
# With custom environment
k6 run --env BASE_URL=https://staging.enchun.tw tests/k6/public-browsing.js
# With custom stages
k6 run --env STAGED_USERS=200 --env STAGED_DURATION=10m tests/k6/public-browsing.js
Run All Tests
# Using the npm script
pnpm test:load
# Or manually
k6 run tests/k6/public-browsing.js
k6 run tests/k6/admin-operations.js
k6 run tests/k6/api-performance.js
Run with Output Options
# Generate JSON report
k6 run --out json=results.json tests/k6/public-browsing.js
# Generate HTML report (requires k6-reporter)
k6 run --out json=results.json tests/k6/public-browsing.js
k6-reporter results.json --output results.html
Interpreting Results
Key Metrics
-
Response Time (p95): 95th percentile response time
- ✅ Pass: < 500ms
- ❌ Fail: >= 500ms
-
Error Rate: Percentage of failed requests
- ✅ Pass: < 1%
- ❌ Fail: >= 1%
-
Throughput: Requests per second
- ✅ Pass: > 100 req/s for API, > 50 req/s for pages
- ❌ Fail: Below threshold
-
Virtual Users (VUs): Active concurrent users
- Should sustain target VUs for the full duration
Example Output
✓ Status is 200
✓ Response time < 500ms
✓ Page content loaded
checks.........................: 100.0% ✓ 12000 ✗ 0
data_received..................: 15 MB 125 kB/s
data_sent......................: 2.1 MB 18 kB/s
http_req_blocked...............: avg=1.2ms min=0.5µs med=1µs max=125ms
http_req_connecting............: avg=500µs min=0s med=0s max=45ms
http_req_duration..............: avg=185.3ms min=45ms med=150ms max=850ms p(95)=420ms
http_req_failed................: 0.00% ✓ 0 ✗ 12000
http_req_receiving.............: avg=15ms min=10µs med=50µs max=250ms
http_req_sending...............: avg=50µs min=5µs med=20µs max=5ms
http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s
http_req_waiting...............: avg=170ms min=40ms med=140ms max=800ms
http_reqs......................: 12000 100 req/s
iteration_duration.............: avg=5.2s min=1.2s med=5s max=12s
iterations.....................: 2400 20 /s
vus............................: 100 min=100 max=100
vus_max........................: 100 min=100 max=100
CI/CD Integration
GitHub Actions
name: Load Tests
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM
workflow_dispatch:
jobs:
k6:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: grafana/k6-action@v0.3.1
with:
filename: tests/k6/public-browsing.js
env:
BASE_URL: ${{ secrets.STAGING_URL }}
Troubleshooting
Connection Refused
Error: connect attempt failed
Solution:
- Ensure the backend server is running
- Check
BASE_URLis correct - Verify firewall settings
High Error Rate
Error: http_req_failed > 1%
Possible Causes:
- Server overload (reduce VUs)
- Database connection issues
- Authentication failures
- Network issues
Debug:
# Run with fewer users
k6 run --env STAGED_USERS=10 tests/k6/public-browsing.js
# Check server logs
pnpm dev
# In another terminal, watch logs while tests run
Slow Response Times
Error: p(95) >= 500ms
Possible Causes:
- Unoptimized database queries
- Missing indexes
- Large payloads
- Server resource constraints
Next Steps:
- Review database queries
- Check caching strategies
- Optimize images/assets
- Scale server resources
Performance Baseline
Initial baseline (to be established):
| Test | p95 (ms) | Error Rate | Throughput |
|---|---|---|---|
| Public Browsing | TBD | TBD | TBD |
| Admin Operations | TBD | TBD | TBD |
| API Performance | TBD | TBD | TBD |
Update this table after first test run to establish baseline.
Resources
Maintenance
- Review and update test scenarios quarterly
- Adjust load profiles based on real traffic patterns
- Update thresholds based on business requirements
- Add new tests for new features
Last Updated: 2025-01-31 Owner: QA Team