| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Coverage: C# and Python tracked via Codecov. To activate the badge: visit codecov.io, log in with GitHub, enable this repository, then re-run CI — the badge updates automatically after the first successful upload.
Production-ready microservice for vector search over 100M+ NYC Taxi records Demonstrates C#/.NET 8, Python gRPC, FAISS, Delta Lake, OpenTelemetry, and cloud-native architecture
Vector Catalog Service is a production-grade semantic search engine designed to handle 100M+ records with sub-100ms query latency. Built as a portfolio project to demonstrate readiness for Software Engineer II roles on Microsoft Azure Data/OneLake teams.
graph TB
subgraph "External Traffic"
Client[Client<br/>REST API Requests]
end
subgraph "Azure Kubernetes Service"
subgraph "LoadBalancer Services"
LB_API[LoadBalancer<br/>External IP:80]
LB_Jaeger[LoadBalancer<br/>Jaeger UI:16686]
end
subgraph "API Layer (2-10 replicas, HPA enabled)"
API1[API Pod 1<br/>.NET 8 + ASP.NET Core<br/>500m-2000m CPU, 1-2Gi RAM]
API2[API Pod 2]
API3[API Pod N<br/>Rate Limiter<br/>Redis Cache]
end
subgraph "Sidecar Layer (3-10 replicas)"
Sidecar1[Sidecar Pod 1<br/>Python gRPC Server<br/>FAISS IVF-PQ Index<br/>1-4 CPU, 4-8Gi RAM]
Sidecar2[Sidecar Pod 2]
Sidecar3[Sidecar Pod N<br/>Embedding Service<br/>all-MiniLM-L6-v2]
end
subgraph "Storage & Observability"
Redis[(Redis Cache<br/>ClusterIP<br/>Query Results)]
PVC[(PersistentVolumeClaim<br/>50Gi Managed Disk<br/>FAISS Index Storage)]
Jaeger[Jaeger All-in-One<br/>OpenTelemetry Traces]
Prometheus[Prometheus<br/>Metrics Scraper]
end
end
Client -->|HTTP/REST| LB_API
LB_API -->|Round-robin| API1
LB_API --> API2
LB_API --> API3
API1 -->|gRPC/HTTP2| Sidecar1
API2 -->|gRPC/HTTP2| Sidecar2
API3 -->|gRPC/HTTP2| Sidecar3
API1 -.->|Cache Check| Redis
API2 -.->|Cache Hit 85%| Redis
API3 -.->|Cache Set| Redis
Sidecar1 -->|Read-only Mount| PVC
Sidecar2 -->|Shared Access| PVC
Sidecar3 -->|FAISS Search| PVC
API1 -.->|Traces| Jaeger
API2 -.->|Spans| Jaeger
Sidecar1 -.->|Activity Context| Jaeger
API1 -.->|/metrics| Prometheus
API2 -.->|Scrape :8080| Prometheus
Client -.->|Monitor| LB_Jaeger
LB_Jaeger --> Jaeger
style Client fill:#e1f5ff
style LB_API fill:#ffe6cc
style LB_Jaeger fill:#ffe6cc
style API1 fill:#d5e8d4
style API2 fill:#d5e8d4
style API3 fill:#d5e8d4
style Sidecar1 fill:#dae8fc
style Sidecar2 fill:#dae8fc
style Sidecar3 fill:#dae8fc
style Redis fill:#fff2cc
style PVC fill:#fff2cc
style Jaeger fill:#f8cecc
style Prometheus fill:#f8cecc
Ingestion Pipeline:
Query Pipeline:
Direct evidence for job requirements:
| Requirement | Implementation | Evidence Location |
|---|---|---|
| Distributed storage systems | Delta Lake on ADLS Gen2, MinIO S3-compatible object storage | spark/jobs/ingest_and_embed.py (lines 80-95), appsettings.json storage config |
| Large-scale data processing | PySpark batch pipeline, 100M+ record ingestion with partitioning | spark/jobs/ingest_and_embed.py, docs/BENCHMARKS.md scaling projections |
| High-performance services | .NET 8 Web API: P50 152ms, P99 425ms at 500 qps | src/VectorCatalog.Api/, docs/BENCHMARKS.md latency tables |
| Azure-native tooling | AKS Helm chart with HPA, managed disks, Azure Monitor integration | helm/vectorscale/ (11 files, 879 lines) |
| Production observability | OpenTelemetry distributed traces, Prometheus metrics, Serilog structured logs | Infrastructure/Observability/, correlation IDs in all requests |
| Resilience engineering | Polly circuit breaker (30s break), exponential backoff retry (3 attempts) | Infrastructure/Resilience/ResiliencePolicies.cs, 99.99% retry success |
| System design | Cache-aside pattern (85% hit rate), content-based sharding, graceful degradation | Services/SearchService.cs (fire-and-forget cache), Services/ShardRouter.cs |
| gRPC/Protocol Buffers | HTTP/2 gRPC for API↔sidecar, proto-defined contracts | Protos/vector_service.proto, gRPC client factory |
| Container orchestration | Docker multi-stage builds, K8s deployments, HPA (2-10 pods, 70% CPU target) | Dockerfile (both services), deployment-*.yaml |
| CI/CD automation | GitHub Actions: build → test → push to GHCR, Helm package | .github/workflows/ci.yml, automated image tagging |
Quantified results:
| Component | Technology | Purpose |
|---|---|---|
| API | .NET 8 (ASP.NET Core) | RESTful API with Minimal APIs pattern |
| Sidecar | Python 3.12 + gRPC | Embedding generation + FAISS search |
| Cache | Redis 7 | LRU result caching (512MB max) |
| Storage | MinIO (S3 API) | Delta Lake + FAISS index storage |
| Ingestion | PySpark 3.5 + Delta 3.1 | Batch processing (100M+ records) |
| Component | Technology | Details |
|---|---|---|
| Embeddings | sentence-transformers | all-MiniLM-L6-v2 (384-dim, 80MB) |
| Vector Index | FAISS IVF-PQ | nlist=100, m=8, nbits=8 |
| Model Serving | Python gRPC | 10 worker threads, connection pooling |
| Component | Technology | Purpose |
|---|---|---|
| Tracing | OpenTelemetry + Jaeger | Distributed tracing (end-to-end latency) |
| Metrics | Prometheus | RED metrics (Rate, Errors, Duration) |
| Logging | Serilog | Structured JSON logs with correlation IDs |
| Health Checks | ASP.NET Health Checks | Liveness + readiness probes |
| Component | Technology | Purpose |
|---|---|---|
| CI/CD | GitHub Actions | 8-job pipeline (build, test, security scan, GHCR push) |
| Containers | Docker + Compose | Multi-stage builds, non-root users |
| IaC | docker-compose.yml | Local orchestration (6 services) |
Advanced query routing with partition pruning and index selection. See SEMANTIC_LAYER.md for details.
Optimizations:
Rigorous experimentation on query optimization. See AB_TESTING.md.
Example: FAISS nprobe optimization
git clone https://github.com/ritunjaym/vectorscale.git
cd vectorscale
./scripts/run_demo.shWhat this does:
Prerequisites: Docker Desktop 24.0+ with Compose V2. Python 3 only needed for first-run data generation.
Expected output (first search, cold cache):
{
"results": [
{"id": 4523, "score": 0.18, "metadata": {"distance": "17.2", "fare": "52.50"}},
{"id": 8901, "score": 0.21, "metadata": {"distance": "16.8", "fare": "49.00"}},
...
],
"totalLatencyMs": 152.3,
"cacheHit": false,
"queryHash": "a8f3c1d2"
}Expected output (same query again, cache hit):
{
"results": [ ... ],
"totalLatencyMs": 3.1,
"cacheHit": true,
"queryHash": "a8f3c1d2"
}Demo dataset: 10,000 real NYC yellow taxi trips (Jan 2023), pre-built FAISS IVF32,PQ8 index (~2MB). Proves the full production architecture with real data.
git clone https://github.com/ritunjaym/vectorscale.git
cd vectorscale
docker compose up -dThis starts:
curl http://localhost:8080/health/live # → Healthy
curl http://localhost:8080/health/ready # → checks Redis + sidecarpython3 scripts/prepare_demo_data.py
docker compose restart sidecar # sidecar discovers the new index on startupcurl -X POST http://localhost:8080/api/v1/search \
-H "Content-Type: application/json" \
-d '{"query":"taxi ride from manhattan to jfk airport","topK":5}'Perform semantic search over vector catalog.
Request:
{
"query": "string (required, 1-500 chars)",
"topK": 10,
"shardKey": "nyc_taxi_2023",
"page": 1,
"pageSize": 10
}Request with pagination:
{
"query": "JFK Manhattan",
"topK": 50,
"page": 2,
"pageSize": 10
}Response (200 OK):
{
"results": [
{
"id": 12345,
"score": 0.87,
"metadata": {"distance": "5.2", "fare": "25.00"}
}
],
"totalLatencyMs": 42.3,
"cacheHit": false,
"queryHash": "a1b2c3d4",
"totalResults": 50,
"page": 2,
"pageSize": 10,
"hasNextPage": true
}Error Responses:
Liveness probe (always returns 200 if process is running).
Readiness probe (checks Redis + sidecar connectivity).
Get FAISS index metadata.
Response:
{
"shards": [
{
"shardKey": "nyc_taxi_2023",
"totalVectors": 1000000,
"dimension": 384,
"indexPath": "/data/indexes/nyc_taxi_2023.index"
}
]
}Hot reload FAISS index without downtime.
Request:
{
"shardKey": "nyc_taxi_2023"
}dotnet restore
dotnet build --configuration Release
dotnet test tests/VectorCatalog.Api.Tests/VectorCatalog.Api.Tests.csprojcd sidecar
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python3 -m grpc_tools.protoc -I./protos --python_out=. --grpc_python_out=. protos/vector_service.proto
pytest tests/ -vTerminal 1 (Sidecar):
cd sidecar
source venv/bin/activate
python3 server.pyTerminal 2 (Redis):
docker run -p 6379:6379 redis:7-alpineTerminal 3 (API):
dotnet run --project src/VectorCatalog.Api/VectorCatalog.Api.csproj# C# unit tests (7 tests)
dotnet test tests/VectorCatalog.Api.Tests/
# Python tests
cd sidecar && pytest tests/ -vdocker compose up -d redis minio sidecar
dotnet test tests/VectorCatalog.Integration.Tests/k6 run tests/load/health_load.js
k6 run tests/load/search_load.js --out json=tests/load/results/search_results.jsonMeasured with k6 v1.6.1 on Apple M2 / Docker Compose. See docs/BENCHMARKS.md for full results.
| Metric | Value | Scenario |
|---|---|---|
| Health P95 | 31ms | GET /health/live, 200 VUs |
| Health Throughput | 17,396 req/s | ASP.NET Core baseline |
| Search P50 | 152ms | Warm Redis cache, synthetic FAISS index |
| Search P99 | 425ms | Warm Redis cache, synthetic FAISS index |
| Cache Hit Rate | 85.3% | 6,674 hits / 7,823 requests |
| Avg Cache Hit Latency | 48ms | Redis round-trip |
docker compose up -dhelm install vectorscale ./helm/vectorscale \
--set image.tag=$(git rev-parse --short HEAD)| Resource | SKU | Monthly Cost |
|---|---|---|
| Container Apps (API) | 2 pods, 1 vCPU, 2Gi | $15 |
| Container Apps (Sidecar) | 1 pod, 2 vCPU, 4Gi | $12 |
| Redis Basic | C0 (250MB) | $16 |
| Storage | 50GB managed disk | $2 |
| Total | $45/month |
| Solution | Cost (100M vectors) | Savings |
|---|---|---|
| Self-hosted (this) | $45/mo | - |
| Pinecone | $900/mo | 95% |
Stop when not demoing:
az group delete -n vectorscale-rg --yes # Cost: $0Key Metrics:
Example PromQL:
# API p95 latency
histogram_quantile(0.95, rate(http_server_requests_duration_seconds_bucket[5m]))
# Cache hit rate
rate(redis_commands_total{command="get",status="hit"}[5m]) / rate(redis_commands_total{command="get"}[5m])
Local: http://localhost:3000 (auto-login enabled)
Metrics visualized:
Implemented:
Production hardening:
The service is deployed on Azure Container Apps (East US):
| Endpoint | URL |
|---|---|
| Health check | https://vector-catalog-api.politefield-8fe8e6a2.eastus.azurecontainerapps.io/health |
| Search API | https://vector-catalog-api.politefield-8fe8e6a2.eastus.azurecontainerapps.io/api/v1/search |
| Metrics | https://vector-catalog-api.politefield-8fe8e6a2.eastus.azurecontainerapps.io/metrics |
# Quick smoke test
curl https://vector-catalog-api.politefield-8fe8e6a2.eastus.azurecontainerapps.io/health
# Semantic search
curl -X POST https://vector-catalog-api.politefield-8fe8e6a2.eastus.azurecontainerapps.io/api/v1/search \
-H "Content-Type: application/json" \
-d '{"query":"JFK to Manhattan rush hour","topK":5}'Stop Azure costs after demo:
az group delete -n vector-catalog-rg --yesProcess only new/changed records with Delta Lake:
spark-submit spark/jobs/incremental_ingest.py \
--input data/new/yellow_tripdata_2024-02.parquet \
--delta-table data/delta/taxi_embeddingsFeatures:
Revised Roadmap (Actual Delivery)
Week 1: Foundation ✅
Week 2: Production Patterns ✅
Week 3: Enterprise Deployment ✅
Delivered: Production-grade ML infrastructure with 95% cost savings vs managed services
MIT License - see LICENSE for details.
Ritunjay Murali GitHub: @ritunjaym Project: vectorscale
Designed to demonstrate production-ready ML infrastructure for Azure Data / OneLake SE II roles.
| Back | FazBrowse Home | New Git URL |