WAF & Rate Limiting
Request protection, rate limiting, and security monitoring
WAF & Rate Limiting
Data Border uses Arcjet for Web Application Firewall (WAF) protection and intelligent rate limiting.
Arcjet Protection
Arcjet provides real-time protection against:
- Bot attacks
- Credential stuffing
- Suspicious request patterns
- DDoS attempts
- Common web exploits
Configuration
Enable by setting:
ARCJET_KEY=ajkey_your_key_here
When configured, all requests pass through Arcjet's security layer before reaching Data Border.
Rate Limits
Per-Endpoint Limits
| Endpoint | Limit | Window | Scope |
|---|---|---|---|
/auth/initialize | 5 requests | 10 seconds | Per IP |
/auth/redirect | No additional limit | - | Called by Amazon |
/api/pii/getPII/* | 1 request | 1 hour | Per order |
/api/pii/getFile | 50 requests | 24 hours | Per tenant |
/api/* | Adaptive | - | Per IP (Arcjet) |
/passthrough-api/* | Amazon limits | - | Per seller |
PII Access Throttling
The strictest rate limiting applies to PII access:
flowchart TD
A[GET /api/pii/getPII/ORDER_123] --> B{Last access?}
B -->|> 1 hour ago| C[Allow request]
B -->|< 1 hour ago| D[429 Too Many Requests]
C --> E[Log access time]
E --> F[Return PII data]This prevents bulk extraction of customer data.
File Operation Limits
File operations are limited to prevent abuse:
| Operation | Daily Limit | Per |
|---|---|---|
getFile | 50 | Tenant |
writeFile | No hard limit | Requires recent PII access |
deleteFile | No hard limit | - |
Adaptive Rate Limiting
Arcjet uses machine learning to detect suspicious patterns:
What Triggers Limits
- Unusually high request volume
- Requests from known bad IPs
- Bot-like request patterns
- Rapid authentication attempts
- Geographic anomalies
Response Headers
Rate-limited responses include:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995260
Suspicious Activity Detection
Data Border monitors for patterns that may indicate misuse:
Flagged Behaviors
| Behavior | Response |
|---|---|
| Accessing PII for shipped orders | Logged as suspicious |
| Accessing PII for other sellers' orders | Blocked + logged |
| Repeated failed authentication | Rate limited |
| Unusual access patterns | Logged for review |
Logging
Suspicious activity is logged with full context:
{
"type": "security",
"event": "suspicious_pii_access",
"orderId": "123-456-789",
"sellerId": "seller_abc",
"tenantId": "tenant_xyz",
"reason": "order_already_shipped",
"ip": "203.0.113.42",
"userAgent": "WMS-Client/1.0",
"timestamp": "2024-01-15T10:30:00.000Z"
}
IP-Based Protection
Blocked by Default
- Known malicious IPs (threat intelligence)
- Tor exit nodes (configurable)
- Data center IPs without proper identification
Trusted Sources
Requests from Amazon's infrastructure are trusted for:
- OAuth callbacks
- Notification webhooks (when verified)
Request Validation
Header Validation
Required headers are validated before processing:
// Enforced for all authenticated endpoints
const requiredHeaders = [
'x-seller-access-token', // For seller ops
'x-amazon-token-secret' // For Amazon access
]
// Validated
headers['x-original-url'] // Must be whitelisted carrier
Body Validation
Request bodies are validated using Zod schemas:
// Example: Create tenant validation
const createTenantSchema = z.object({
name: z.string().min(1),
redirectOrigin: z.string().url().startsWith('https://')
})
HTTPS Enforcement
All traffic must use HTTPS:
flowchart LR
A[HTTP Request] -->|Redirect| B[HTTPS]
C[HTTPS Request] --> D[Data Border]- HTTP requests are redirected to HTTPS
- HSTS headers are set
- TLS 1.2+ required
CORS Configuration
Cross-Origin Resource Sharing is configured per route:
| Route | CORS |
|---|---|
/health-check | Open |
/auth/* | Configured per tenant |
/api/* | Configured per tenant |
Error Responses
Rate Limit Exceeded
{
"is_adb_error": true,
"success": false,
"error": {
"message": "Rate limit exceeded",
"details": "Please retry after 60 seconds"
}
}
Security Block
{
"is_adb_error": true,
"success": false,
"error": {
"message": "Request blocked",
"details": "Suspicious activity detected"
}
}
Invalid Token
{
"is_adb_error": true,
"success": false,
"error": {
"message": "Invalid or expired token"
}
}
Implementing Client-Side Handling
Retry with Backoff
async function callAdbWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options)
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 60
console.log(`Rate limited, waiting ${retryAfter}s`)
await sleep(retryAfter * 1000)
continue
}
if (response.status === 403) {
// Don't retry security blocks
throw new SecurityBlockError(await response.json())
}
return response
}
throw new Error('Max retries exceeded')
}
PII Throttle Handling
async function getPII(orderId) {
try {
return await adb.get(`/api/pii/getPII/${orderId}`)
} catch (error) {
if (error.status === 429) {
// Already fetched recently, use cached or skip
const cached = await cache.get(`pii:${orderId}`)
if (cached) return cached
// Wait and retry
await sleep(60 * 60 * 1000) // 1 hour
return await getPII(orderId)
}
throw error
}
}
Monitoring & Alerts
Key Metrics
| Metric | Alert Threshold |
|---|---|
| 429 response rate | > 5% of requests |
| Security blocks | Any |
| Auth failures | > 10/minute |
| PII access attempts on blocked orders | Any |
Log Analysis
Search for security events:
# Find security blocks
grep '"type":"security"' /var/log/adb.log | jq
# Find rate limit events
grep '429' /var/log/adb.log | jq '.path, .ip'
Best Practices
Avoid Rate Limits
- Cache tokens - Don't regenerate on every request
- Batch operations - Combine requests where possible
- Implement backoff - Respect Retry-After headers
- Use webhooks - Subscribe to notifications instead of polling
Secure Your Integration
- Validate tokens - Check expiry before use
- Rotate secrets - Generate new tenant if compromised
- Monitor logs - Watch for unusual patterns
- Use least privilege - Only access what's needed
