API Rate Limits and Business Strategy¶
Business Context¶
API rate limiting в Saga служит нескольким критическим бизнес-целям:
- Fair Resource Allocation - равномерное распределение ресурсов между пользователями
- Anti-Abuse Protection - защита от злоупотреблений и DoS атак
- Cost Management - контроль расходов на blockchain gas и infrastructure
- Quality of Service - гарантированная производительность для всех пользователей
- Scalability Planning - управляемый рост нагрузки на систему
🔢 API Rate Limits Configuration¶
1. Faucet Limits¶
Business Logic:
- Daily Limit: 1,000 USDC per wallet per 24 hours
- Cooldown Period: 24 hours между requests
- Purpose: Prevent faucet abuse while allowing testing
Configuration:
# config/limits.yaml
faucet:
amount_usdc: "1000.00"
cooldown_hours: 24
max_daily_requests: 1
blockchain:
gas_limit_usdc: 100000
gas_limit_staking: 200000
Implementation:
// backend/shared/services/faucet_service.go
func (s *FaucetService) ValidateRequest(walletAddress string) error {
// Check last request time
lastRequest, err := s.repo.GetLastFaucetRequest(walletAddress)
if err == nil && time.Since(lastRequest) < 24*time.Hour {
remainingTime := 24*time.Hour - time.Since(lastRequest)
return fmt.Errorf("cooldown active: %s remaining", remainingTime)
}
// Check daily limit
dailyCount, err := s.repo.GetDailyFaucetCount(walletAddress)
if dailyCount >= 1 {
return errors.New("daily limit exceeded")
}
return nil
}
Business Rationale:
- ✅ 1,000 USDC достаточно для comprehensive testing
- ✅ 24h cooldown предотвращает sybil attacks
- ✅ Один request в день = reasonable usage pattern
- ✅ Можно создать multiple wallets для дополнительных средств
2. Investment Strategy Limits¶
Amount Limits per Strategy:
| Strategy | Min Amount | Max Amount | Business Reason |
|---|---|---|---|
| Conservative (5%) | $10 | $10,000 | Entry barrier low, cap для risk management |
| Balanced (10%) | $10 | $10,000 | Same limits для consistency |
| Aggressive (20%) | $10 | $10,000 | Same limits для consistency |
Configuration:
# config/limits.yaml
limits:
investment_strategies:
- id: 1
name: "Conservative"
min_amount: "10.00"
max_amount: "10000.00"
apy: 5.0
- id: 2
name: "Balanced"
min_amount: "10.00"
max_amount: "10000.00"
apy: 10.0
- id: 3
name: "Aggressive"
min_amount: "10.00"
max_amount: "10000.00"
apy: 20.0
Validation Logic:
func (s *InvestmentService) ValidateAmount(strategyID int, amount SafeDecimal) error {
strategy := s.config.GetInvestmentStrategy(strategyID)
if amount.LessThan(strategy.MinAmount) {
return fmt.Errorf("amount below minimum: $%s (min: $%s)",
amount.String(),
strategy.MinAmount.String(),
)
}
if amount.GreaterThan(strategy.MaxAmount) {
return fmt.Errorf("amount exceeds maximum: $%s (max: $%s)",
amount.String(),
strategy.MaxAmount.String(),
)
}
return nil
}
Business Rationale:
- $10 minimum: Low entry barrier для новых пользователей
- $10,000 maximum: Risk management (testnet MVP limits)
- Uniform limits: Simplicity для пользователей
- Future expansion: Можно увеличить для mainnet production
3. Withdrawal Limits¶
Daily Withdrawal Limits:
# config/limits.yaml
withdrawal:
min_amount: "1.00"
max_amount_per_request: "10000.00"
max_daily_amount: "50000.00"
cooldown_between_requests_minutes: 5
Validation:
func (s *WithdrawalService) ValidateWithdrawal(userID int64, amount SafeDecimal) error {
// 1. Check minimum
if amount.LessThan(NewSafeDecimal("1.00")) {
return errors.New("withdrawal amount below minimum $1")
}
// 2. Check per-request maximum
if amount.GreaterThan(NewSafeDecimal("10000.00")) {
return errors.New("withdrawal exceeds $10,000 per-request limit")
}
// 3. Check daily total
dailyTotal, err := s.repo.GetDailyWithdrawalTotal(userID)
if err != nil {
return err
}
if dailyTotal.Add(amount).GreaterThan(NewSafeDecimal("50000.00")) {
return errors.New("daily withdrawal limit exceeded ($50,000)")
}
// 4. Check cooldown
lastWithdrawal, err := s.repo.GetLastWithdrawal(userID)
if err == nil && time.Since(lastWithdrawal.CreatedAt) < 5*time.Minute {
return errors.New("5-minute cooldown between withdrawals")
}
return nil
}
Business Rationale:
- $1 minimum: Avoid dust withdrawals (gas costs)
- $10,000 per request: Anti-fraud limit
- $50,000 daily: Risk management cap
- 5-minute cooldown: Prevent accidental double-withdrawals
4. API Request Rate Limits¶
Global Rate Limits:
# config/monitoring.yaml
rate_limiting:
global:
requests_per_second: 100
burst_size: 200
per_user:
requests_per_minute: 60
requests_per_hour: 1000
per_endpoint:
auth:
requests_per_minute: 10
faucet:
requests_per_minute: 1
balance:
requests_per_minute: 30
investments:
requests_per_minute: 20
withdrawals:
requests_per_minute: 5
Implementation (Chi Middleware):
import "github.com/go-chi/httprate"
func SetupRateLimiting(r chi.Router, cfg *config.UnifiedConfig) {
// Global rate limit
r.Use(httprate.LimitByIP(100, 1*time.Second))
// Per-endpoint limits
r.Group(func(r chi.Router) {
r.Use(httprate.LimitByIP(10, 1*time.Minute))
r.Post("/api/auth/wallet/authenticate", authHandler.Authenticate)
})
r.Group(func(r chi.Router) {
r.Use(httprate.LimitByIP(1, 1*time.Minute))
r.Post("/api/faucet/request", faucetHandler.RequestFunds)
})
r.Group(func(r chi.Router) {
r.Use(httprate.LimitByIP(30, 1*time.Minute))
r.Get("/api/user/balance", userHandler.GetBalance)
})
}
Business Rationale:
- 100 req/sec global: Reasonable server capacity
- 60 req/min per user: Normal usage pattern
- Endpoint-specific: Critical endpoints более строгие limits
- Burst allowance: Accommodate legitimate traffic spikes
Business Strategy per Limit Category¶
Strategy 1: Faucet Anti-Abuse¶
Problem: Faucet может быть использован для бесплатного farming testnet токенов.
Solution Strategy:
- One-per-day limit - prevents repeat abuse
- Wallet-based tracking - sybil resistance
- Amount cap (1,000 USDC) - limits total exposure
- Future enhancement: CAPTCHA для дополнительной защиты
Metrics to Monitor:
- Unique wallets per day
- Total USDC distributed
- Repeat offenders (multiple wallets from same IP)
- Faucet request patterns
Success Criteria:
- Average 50-100 unique wallets per day
- <5% repeat requestors per IP
- Total daily distribution <100,000 USDC
Strategy 2: Investment Volume Management¶
Problem: Неограниченные investments создают operational risks.
Solution Strategy:
- $10,000 cap per investment - manageable risk per transaction
- No total portfolio limit - allow accumulation over time
- Strategy-based limits - same limits для consistency
- Admin override capability - для exceptional cases
Metrics to Monitor:
- Average investment size per strategy
- Total Value Locked (TVL) growth rate
- Distribution across strategies (5%, 10%, 20%)
- Large investments (>$5,000) frequency
Success Criteria:
- Average investment: $100-500
- TVL growth: 10-20% monthly
- Strategy distribution: 40% Conservative, 40% Balanced, 20% Aggressive
Strategy 3: Withdrawal Flow Control¶
Problem: Неконтролируемые withdrawals угрожают liquidity.
Solution Strategy:
- Daily limit ($50,000) - prevents bank run
- Per-request limit ($10,000) - fraud protection
- Admin approval for >$1,000 - manual review для крупных сумм
- 5-minute cooldown - prevents accidental duplicates
Metrics to Monitor:
- Daily withdrawal volume
- Withdrawal approval rate (admin)
- Average processing time
- Failed withdrawal reasons
Success Criteria:
- <10% of TVL withdrawn daily
-
95% approval rate для small withdrawals
- <1 hour average processing time
- <1% failed withdrawals due to limits
Strategy 4: API Rate Limiting for Stability¶
Problem: Неограниченный API access может перегрузить систему.
Solution Strategy:
- Tiered limits - global → per-user → per-endpoint
- Burst allowance - accommodate legitimate spikes
- Endpoint-specific - critical endpoints stricter
- 429 Too Many Requests - clear error messaging
Metrics to Monitor:
- API requests per second (RPS)
- Rate limit violations per hour
- Endpoint distribution (which endpoints hit most)
- User behavior patterns
Success Criteria:
- <80% of rate limit capacity used
- <5% requests result in 429 errors
- No single user >20% of total traffic
- Average latency <100ms
Dynamic Limit Adjustment¶
Automatic Scaling¶
Load-based Adjustment:
func (s *RateLimiter) AdjustLimits(ctx context.Context) {
currentLoad := s.metrics.GetCurrentLoad()
if currentLoad > 0.8 {
// High load: reduce limits
s.config.GlobalRPS = 80
s.config.PerUserRPM = 50
logger.WarnStructured("Rate limits reduced due to high load",
"load", currentLoad,
"new_global_rps", 80,
)
} else if currentLoad < 0.5 {
// Low load: restore normal limits
s.config.GlobalRPS = 100
s.config.PerUserRPM = 60
logger.InfoStructured("Rate limits restored",
"load", currentLoad,
)
}
}
Time-based Adjustment:
func (s *RateLimiter) GetPeakHourLimits(hour int) RateLimits {
// Peak hours: 9am-5pm UTC (reduce by 20%)
if hour >= 9 && hour <= 17 {
return RateLimits{
GlobalRPS: 80,
PerUserRPM: 48,
}
}
// Off-peak: normal limits
return RateLimits{
GlobalRPS: 100,
PerUserRPM: 60,
}
}
Manual Override (Admin)¶
Admin Endpoint для Manual Adjustment:
// POST /api/admin/limits/adjust
type LimitAdjustRequest struct {
LimitType string `json:"limit_type"` // "global", "faucet", "withdrawal"
Value float64 `json:"value"`
Reason string `json:"reason"`
}
func (h *AdminHandler) AdjustLimits(w http.ResponseWriter, r *http.Request) {
var req LimitAdjustRequest
json.NewDecoder(r.Body).Decode(&req)
// Validate admin
adminEmail := r.Context().Value("admin_email").(string)
// Apply adjustment
err := h.limiter.SetLimit(req.LimitType, req.Value)
if err != nil {
http_helpers.SendError(w, http.StatusBadRequest, err.Error())
return
}
// Audit log
logger.InfoStructured("Rate limit manually adjusted",
"admin", adminEmail,
"limit_type", req.LimitType,
"new_value", req.Value,
"reason", req.Reason,
)
http_helpers.SendSuccess(w, map[string]interface{}{
"message": "Limit adjusted successfully",
"limit_type": req.LimitType,
"new_value": req.Value,
})
}
Business Metrics and KPIs¶
Key Performance Indicators¶
User Experience KPIs:
- API Latency: <100ms average (target: 50ms)
- Rate Limit Hit Rate: <5% of requests
- Error Rate: <1% of total requests
- Successful Transactions: >99% success rate
Business Health KPIs:
- TVL Growth: 10-20% monthly
- Active Users: 100-500 daily active wallets
- Faucet Efficiency: 50-100 unique users per day
- Withdrawal Approval Rate: >95% for small amounts
Operational KPIs:
- Server Load: <80% capacity
- Gas Costs: <$500/day for blockchain operations
- Database Performance: <50ms query time
- Uptime: >99.9%
Monitoring Dashboard¶
Prometheus Metrics:
var (
apiRequestsTotal = promauto.NewCounterVec(
prometheus.CounterOpts{
Name: "api_requests_total",
Help: "Total API requests",
},
[]string{"endpoint", "status"},
)
rateLimitViolations = promauto.NewCounterVec(
prometheus.CounterOpts{
Name: "rate_limit_violations_total",
Help: "Rate limit violations",
},
[]string{"limit_type"},
)
withdrawalVolume = promauto.NewGaugeVec(
prometheus.GaugeOpts{
Name: "withdrawal_volume_usdc",
Help: "Withdrawal volume in USDC",
},
[]string{"period"}, // "hourly", "daily"
)
)
Grafana Dashboard Panels:
- API Performance
- Requests per second (time series)
- Latency distribution (histogram)
-
Error rate (gauge)
-
Rate Limiting
- Violations by endpoint (bar chart)
- Top violators (table)
-
Limit utilization (gauge)
-
Business Metrics
- TVL growth (time series)
- Investment distribution (pie chart)
- Withdrawal volume (time series)
Alerting Strategy¶
Critical Alerts (PagerDuty)¶
High Priority:
alerts:
- name: RateLimitViolationSpike
condition: rate_limit_violations > 100 per minute
action: Page on-call engineer
severity: critical
- name: WithdrawalLimitBreach
condition: daily_withdrawals > $50,000
action: Alert admin team
severity: high
- name: APILatencyHigh
condition: avg_latency > 500ms for 5 minutes
action: Page on-call engineer
severity: critical
Medium Priority:
- name: FaucetAbuseDetected
condition: same_ip_multiple_wallets > 5
action: Notify security team
severity: medium
- name: InvestmentCapApproaching
condition: single_investment > $8,000
action: Notify business team
severity: medium
Email Notifications¶
Business Events:
- New user registration (>10 per hour)
- Large investment (>$5,000)
- Withdrawal approval pending
- Daily summary reports
System Events:
- Rate limit adjustments
- Configuration changes
- Deployment events
Related Documentation¶
Technical Implementation:¶
- API Documentation - API endpoints reference
Business Decision Framework¶
When to Adjust Limits¶
Increase Limits When:
- ✅ Server capacity underutilized (<50%)
- ✅ User complaints about restrictiveness
- ✅ Business growth requires higher throughput
- ✅ No security incidents in past 30 days
Decrease Limits When:
- ⚠️ Server load consistently >80%
- ⚠️ Security incidents detected
- ⚠️ Abuse patterns identified
- ⚠️ Cost overruns (gas, infrastructure)
Temporary Adjustments:
- 🔧 Marketing campaigns (higher traffic expected)
- 🔧 Maintenance windows (reduce load)
- 🔧 Security incidents (temporary lockdown)
- 🔧 Testing new features (gradual rollout)
Approval Process¶
Permanent Limit Changes:
- Business proposal with rationale
- Technical feasibility review
- Security impact assessment
- Executive approval (for significant changes)
- Phased rollout with monitoring
Temporary Adjustments:
- Admin authorization
- Audit log entry
- Duration specification
- Automatic revert after period
📋 Метаданные¶
Версия: 2.4.82
Обновлено: 2025-10-21
Статус: Published