A distributed, shard-based metadata query engine built with a Python orchestration layer and horizontally scaled retrieval nodes. The system demonstrates distributed coordination, connection pooling, tail latency mitigation, and policy-aware filtering under load.
Client
↓
Python Orchestrator (FastAPI)
↓
-----------------------------------------
| node1 | node2 | node3 | node4 | node5 |
-----------------------------------------
Shard-based Retrieval Services
- Async fan-out to all shards
- Timeout-based shard coordination
- Partial result handling
- Policy-aware filtering
- Global deterministic sorting
- Pagination
- Per-shard latency tracking
- Connection pooling
- Independent FastAPI services
- Each loads a different dataset
- Performs local search on metadata
- Exposes
/searchand/health
Data is partitioned across 5 independent retrieval nodes.
This simulates:
- Horizontal scaling
- Distributed metadata indexing
- Independent shard responsibility
The orchestrator queries all shards concurrently:
asyncio.wait(tasks, timeout=SHARD_TIMEOUT_S)This ensures:
- Parallel shard execution
- Reduced query latency
- Non-blocking coordination
Instead of waiting indefinitely for slow shards:
- Coordinator waits up to 300ms
- Cancels slow shard requests
- Returns partial results
Response includes:
{
"partial": true,
"timed_out_nodes": [....]
}This models real distributed search engines.
A global httpx.AsyncClient is initialized at application startup:
httpx.AsyncClient(
limits=httpx.Limits(
max_connections=2000,
max_keepalive_connections=1000
)
)This enables:
- TCP connection reuse
- Reduced handshake overhead
- Controlled resource usage
- High-QPS scalability
Documents are filtered based on:
- Visibility
- Allowed roles
doc["visibility"] == "public"
and role in doc["allowed_roles"]This simulates enterprise access control enforcement at the coordination layer.
All merged shard results are sorted globally before pagination.
Prevents:
- Inconsistent pagination
- Order instability
- Non-deterministic page results
Concurrency is calculated using Little’s Law:
Concurrency = QPS × Latency
Example:
- 3,000 QPS
- 5 shards
- 120ms shard latency
Outbound calls per second:
3,000 × 5 = 15,000
Concurrent shard calls:
15,000 × 0.12 = 1,800
Connection pool limits are configured accordingly.
- Distributed shard-based retrieval
- Async orchestration
- Shard timeout budget
- Partial response signaling
- Per-shard latency measurement
- Deterministic sorting
- Pagination
- Connection pooling
- Resource lifecycle management
docker compose up --buildAccess:
http://localhost:9000/query?q=ai
{
"total_results": 12,
"page": 1,
"limit": 5,
"partial": false,
"timed_out_nodes": [],
"shard_latencies_ms": {
"http://node1:8000/search": 112.4
},
"results": [...]
}| Choice | Reason |
|---|---|
| Timeout-based partial results | Availability over completeness |
| Global sorting before pagination | Deterministic user experience |
| Connection pooling | High throughput and resource efficiency |
| Centralized policy filtering | Consistent enforcement |
- C++ retrieval module implementation
- Inverted indexing instead of linear scan
- Prometheus metrics export
- Circuit breaker pattern
- Hedged requests (replica querying)
- Load testing validation
- Distributed tracing support
- Distributed coordination patterns
- Tail latency mitigation strategies
- Connection pooling & lifecycle management
- Horizontal sharding architecture
- Production-oriented API design
- Performance modeling using concurrency math