Deploying Dike in mission-critical LegalTech environments requires engineering for resilience against rate limits, transient network partitions, and heavy inference loads.
Rendering diagram...
1. Exponential Backoff with Full Jitter
When handling 429 rate_limited or transient 503 upstream_unavailable errors, implement exponential backoff with full jitter to avoid the "thundering herd" problem:
sleep_time = random(0, min(max_sleep, base_sleep * (2 ^ attempt)))Python Implementation (tenacity)
import httpx
from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_random_exponential
class DikeTransientError(Exception):
pass
@retry(
wait=wait_random_exponential(multiplier=1, max=30),
stop=stop_after_attempt(5),
retry=retry_if_exception_type(DikeTransientError),
)
def call_dike_resilient(url: str, payload: dict, api_key: str):
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
with httpx.Client() as client:
res = client.post(url, headers=headers, json=payload, timeout=20.0)
if res.status_code in (429, 503):
raise DikeTransientError(f"Transient error [{res.status_code}]: {res.text}")
res.raise_for_status()
return res.json()2. In-Memory / Redis Caching for Immutable Statutes
Document text returned by GET /v1/document/{canonical_id} changes very infrequently once promulgated.
Recommended Caching Policy
canonical_idText (/v1/document/*): Cache in Redis with a TTL of 7 to 30 days.- Jurisdictions Catalog (
/v1/jurisdictions): Cache in memory for 24 hours. - Citation Normalization (
/v1/cite): Cache normalized queries for 7 days. - Search & Reason (
/v1/search,/v1/reason): Cache by exact query hash for 1 hour (or bypass cache if real-time queries are required).
3. Dynamic Rate Limit Budgeting
Inspect the X-RateLimit-Remaining header in background workers (e.g. Celery / BullMQ):
// workers/legal-ingestion-worker.ts
async function processBatch(citations: string[]) {
for (const citation of citations) {
const res = await fetch('https://api.dike.it.com/v1/cite', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.DIKE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ citation }),
});
const remaining = parseInt(res.headers.get('X-RateLimit-Remaining') || '10', 10);
const resetTime = parseInt(res.headers.get('X-RateLimit-Reset') || '0', 10);
// Proactively throttle worker if remaining quota is low
if (remaining < 5) {
const sleepSeconds = Math.max(1, resetTime - Math.floor(Date.now() / 1000));
console.log(`Approaching quota limit. Throttling worker for ${sleepSeconds}s...`);
await new Promise((resolve) => setTimeout(resolve, sleepSeconds * 1000));
}
}
}4. Circuit Breakers for Downstream Reasoning
If POST /v1/reason experiences upstream inference delays during peak hours, use a circuit breaker to fail fast or gracefully degrade to POST /v1/search + cached responses:
// Fallback strategy: If reason fails, fall back to pure hybrid search
async function askLegalSafe(question: string) {
try {
return await askReason(question);
} catch (err) {
console.warn('Reasoning service unavailable. Falling back to hybrid search results...');
const searchResults = await runSearch(question);
return {
answer: 'تعذر الاتصال بمحرك الاستدلال. فيما يلي أهم النصوص القانونية ذات الصلة:',
citations: searchResults.results.map((r: any, idx: number) => ({
marker: idx + 1,
canonical_id: r.canonical_id,
citation_string: r.citation_string,
snippet: r.snippet,
verified: true,
})),
isFallback: true,
};
}
}Next Steps
- Review the Error Catalog for all RFC 7807 codes.
- Explore troubleshooting steps in Common Errors & Fixes.