papers_tech_stack
Scientific Papers Storage โ Detailed Tech Stack & Architecture
System Architecture (Detailed)
Layer 1: Storage Layer
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ S3-Compatible Object Storage โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Option A: AWS S3 Standard (MVP) โ
โ โข โจMATH:0โฉ0.09/GB egress โ
โ โข 99.99% durability, multi-AZ โ
โ โ
โ Option B: Yandex Object Storage (EU/Russia) โ
โ โข S3-API compatible โ
โ โข GDPR compliant, local data residency โ
โ โข ~$0.015/GB/mo (cheaper than AWS) โ
โ โ
โ Option C: MinIO (Self-hosted, scale) โ
โ โข No egress charges (internal network) โ
โ โข Breakeven vs AWS at 7 months โ
โ โข 2x redundancy (RAID-6): 3TB โ 6TB HW โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโ
โ โ
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ PDFs & Blobs โ โ Metadata Cache โ
โ (300GB-3TB) โ โ (JSON, thumbnails)
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
Recommendation: Start AWS S3, migrate to MinIO at 20TB+ with predictable access patterns.
Layer 2: Metadata & Indexing Layer
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PostgreSQL 15 (Primary Metadata & Full-Text Search Index)โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Schema: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ papers (core table) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ โข id (UUID PK) โ โ
โ โ โข doi (unique, indexed) โ โ
โ โ โข title (text, FTS index) โ โ
โ โ โข abstract (text, FTS index) โ โ
โ โ โข authors (JSONB): โ โ
โ โ [{name, orcid, h_index, aff}] โ โ
โ โ โข pub_year (int, indexed) โ โ
โ โ โข journal (varchar) โ โ
โ โ โข keywords (text[], GIN index) โ โ
โ โ โข s3_key (varchar โ URL) โ โ
โ โ โข citation_count (int) โ โ
โ โ โข fwci (float) โ field norm. impact โ โ
โ โ โข normalized_citations (float) โ โ
โ โ โข h_index_contrib (int) โ โ
โ โ โข embedding_id (UUID โ Qdrant) โ โ
โ โ โข language (varchar: en, ru, zh) โ โ
โ โ โข full_text_tsvector (tsvector FTS) โ โ
โ โ โข created_at, updated_at (timestamp)โ โ
โ โ โข openaccess (boolean) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Indices: โ
โ โข UNIQUE idx_doi โ
โ โข GIN idx_keywords (text[]) โ
โ โข GIST idx_full_text (tsvector) โ
โ โข IDX idx_pub_year โ
โ โข IDX idx_fwci DESC (for ranking) โ
โ โข IDX idx_embedding_id โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Instance: t3.medium (MVP) โ r6i.xlarge (1M papers) โ
โ Storage: 100GB (MVP) โ 500GB (production) โ
โ Backup: Automated snapshots (30-day retention) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Layer 3: Vector Search Layer
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Qdrant (Vector Database for Semantic Search) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Collection: papers_embeddings โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Vector Payload Structure: โ โ
โ โ { โ โ
โ โ "id": "uuid", // Qdrant point ID โ โ
โ โ "vector": [768], // Dense embedding โ โ
โ โ "paper_id": "uuid", // Link to PostgreSQL โ โ
โ โ "doi": "string", // For filtering โ โ
โ โ "title": "string", // Metadata โ โ
โ โ "year": 2024, // For temporal search โ โ
โ โ "field": "AI", // For sharding โ โ
โ โ "citation_count": 42 // For ranking boost โ โ
โ โ } โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Configuration: โ
โ โข Vector dimension: 768 (sentence-transformers) โ
โ โข Distance metric: cosine (optimal for embeddings) โ
โ โข Index type: HNSW (Hierarchical Navigable Small World) โ
โ โข Shard count: 1 (MVP) โ 8+ (1M vectors) โ
โ โข Replication factor: 1 (MVP) โ 3 (production) โ
โ โ
โ Performance (Qdrant benchmarks @ 50M vectors): โ
โ โข Query latency (p99): ~100ms โ
โ โข Throughput: 41 QPS @ 99% recall โ
โ โข Memory: ~500GB for 50M vectors (384-dim) โ
โ โ
โ Instance: t3.large (MVP) โ 3รt3.xlarge cluster (prod) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Alternative: pgvector (if <100K vectors) โ simpler ops, integrated with PostgreSQL, slower @ scale
Layer 4: Ingestion Pipeline
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Ingestion Pipeline (Async, Fault-Tolerant) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Upload โ S3 โ SQS/Redis Queue โ Worker Tasks โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ STEP 1: PDF Upload Handler โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Input: PDF file (multipart/form-data) โ โ
โ โ Actions: โ โ
โ โ โข Validate mimetype (application/pdf) โ โ
โ โ โข Generate checksum (SHA-256) โ โ
โ โ โข Upload to S3: /papers/{year}/{doi}.pdf โ โ
โ โ โข Queue extraction task (Redis) โ โ
โ โ Output: S3 key, checksum, file_id โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ STEP 2: Metadata Extraction (PyMuPDF) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Tool: PyMuPDF (fitz) โ 2-3ร faster than PDFMiner โ โ
โ โ Extract: โ โ
โ โ โข Text (all pages) โ โ
โ โ โข Metadata: title, author, creation date โ โ
โ โ โข Page count, PDF version โ โ
โ โ Retry: 3 attempts, exponential backoff โ โ
โ โ Fallback: Tesseract OCR (if corrupted/scanned PDF) โ โ
โ โ Output: structured dict โ store temp in Redis โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ STEP 3: Semantic Metadata Enrichment โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Input: extracted text + metadata โ โ
โ โ LLM Prompt: Extract structured metadata: โ โ
โ โ - Canonical title (normalize) โ โ
โ โ - Authors (full names, affiliations) โ โ
โ โ - DOI / arXiv ID โ โ
โ โ - Abstract (first 500 chars if not in PDF) โ โ
โ โ - Keywords (5-10) โ โ
โ โ Model: Claude 3.5 Haiku (cheap) or GPT-4 (accurate) โ โ
โ โ Cost: ~$0.002/paper โ โ
โ โ Caching: Check CrossRef API first (free!) โ โ
โ โ Output: normalized metadata JSON โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ STEP 4: Cross-Reference Enrichment โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Lookup: CrossRef API (free tier: 50 req/sec) โ โ
โ โ Enrich: โ โ
โ โ โข Canonical DOI โ โ
โ โ โข Published journal/venue โ โ
โ โ โข Publication year (authoritative) โ โ
โ โ โข ISSN/ISBN โ โ
โ โ โข Open access status (via unpaywall.org) โ โ
โ โ Fallback: arXiv API (for preprints) โ โ
โ โ Timeout: 5 sec per paper (skip if slow) โ โ
โ โ Output: enriched_metadata โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ STEP 5: Embedding Generation โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Input: title + abstract (max 512 tokens) โ โ
โ โ Model: sentence-transformers/all-MiniLM-L6-v2 โ โ
โ โ (384-dim, fast, good recall on academic texts) โ โ
โ โ Alternative: all-mpnet-base-v2 (768-dim, slower) โ โ
โ โ Batch processing: 32 papers/batch for efficiency โ โ
โ โ Output: 384-dim vector [float32] โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ STEP 6: Database & Vector Index Update โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ PostgreSQL insert: โ โ
โ โ INSERT INTO papers (doi, title, authors, ...) ... โ โ
โ โ Qdrant upsert: โ โ
โ โ โข Point ID = paper.id (UUID) โ โ
โ โ โข Vector = embedding โ โ
โ โ โข Payload = {doi, title, year, fwci, ...} โ โ
โ โ Atomicity: Qdrant first (revertible), then PG โ โ
โ โ Output: paper_id (for search) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Worker Configuration: โ
โ โข Framework: Celery (async tasks) + Redis (queue) โ
โ โข Workers: 4 (MVP) โ 16 (production, per CPU) โ
โ โข Timeout: 60 sec per task (with retry) โ
โ โข Concurrency: 2 concurrent papers/worker (GPU shared) โ
โ โข Cost: ~$0.003 per paper (LLM + compute) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Throughput: 500โ1000 papers/hour with 4 workers
Layer 5: Search & Query Layer
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ FastAPI Application (Search & Retrieval) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Endpoint: POST /search (Hybrid) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Request: โ โ
โ โ { โ โ
โ โ "q": "transformer architectures", โ โ
โ โ "limit": 20, โ โ
โ โ "mode": "hybrid", // full-text|semantic|... โ โ
โ โ "filters": { โ โ
โ โ "year": [2020, 2026], // range filter โ โ
โ โ "journal": ["Nature", "Science"], โ โ
โ โ "min_citations": 10, โ โ
โ โ "open_access": true โ โ
โ โ }, โ โ
โ โ "sort_by": "relevance" // or: citations|date โ โ
โ โ } โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Processing Logic: โ โ
โ โ โ โ
โ โ 1. Query Parsing & Normalization โ โ
โ โ โข Lemmatization (spaCy) โ โ
โ โ โข Stop word removal โ โ
โ โ โข Synonym expansion (optional) โ โ
โ โ โ โ
โ โ 2. Full-Text Search (PostgreSQL FTS) โ โ
โ โ SELECT id, title, fwci FROM papers โ โ
โ โ WHERE to_tsvector(full_text) @@ โ โ
โ โ plainto_tsquery('english', q) โ โ
โ โ ORDER BY ts_rank(...) DESC โ โ
โ โ LIMIT 500 (get top candidates) โ โ
โ โ Performance: ~50ms (indexed) โ โ
โ โ โ โ
โ โ 3. Semantic Search (Qdrant) โ โ
โ โ โข Embed query: q โ 384-dim vector โ โ
โ โ โข Query Qdrant: โ โ
โ โ { โ โ
โ โ "vector": query_embedding, โ โ
โ โ "limit": 500, โ โ
โ โ "filter": {...} // year, journal, etc โ โ
โ โ } โ โ
โ โ โข Return: (paper_id, score 0-1) โ โ
โ โ Performance: ~100ms โ โ
โ โ โ โ
โ โ 4. Hybrid Re-Ranking โ โ
โ โ โข Combine scores: 0.3 ร fts_rank + 0.7 ร sem โ โ
โ โ โข Boost by FWCI (field-normalized citations) โ โ
โ โ โข Apply diversity penalty (avoid duplicates) โ โ
โ โ โ โ
โ โ 5. Result Enrichment โ โ
โ โ โข Fetch full metadata from PostgreSQL โ โ
โ โ โข Generate relevance snippets (title match) โ โ
โ โ โข Add S3 download URL (signed, 1-hour expiry) โ โ
โ โ โ โ
โ โ 6. Response (with caching) โ โ
โ โ { โ โ
โ โ "results": [ โ โ
โ โ { โ โ
โ โ "id": "uuid", โ โ
โ โ "title": "...", โ โ
โ โ "authors": [...], โ โ
โ โ "doi": "10.1234/...", โ โ
โ โ "year": 2023, โ โ
โ โ "citations": 42, โ โ
โ โ "fwci": 2.3, // field-normalized โ โ
โ โ "relevance_score": 0.87, โ โ
โ โ "snippet": "...matching text...", โ โ
โ โ "pdf_url": "s3://...signed_url" โ โ
โ โ } โ โ
โ โ ], โ โ
โ โ "total_count": 1234, โ โ
โ โ "search_time_ms": 342 โ โ
โ โ } โ โ
โ โ โ โ
โ โ Caching (Redis): โ โ
โ โ โข Cache full queries (TTL: 1 hour) โ โ
โ โ โข Cache embeddings (TTL: 24 hours) โ โ
โ โ โข Invalidate on new paper added โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Other Endpoints: โ
โ โข POST /papers/upload (accept PDF) โ
โ โข GET /papers/{id} (metadata + download) โ
โ โข GET /papers/by-author/{name} (author search) โ
โ โข GET /search/full-text (FTS only) โ
โ โข GET /search/semantic (semantic only) โ
โ โข GET /stats (ingestion metrics) โ
โ โข GET /health (liveness check) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Latency Target: <500ms (p99) for 100K papers
Summary: Tech Stack Decision Matrix
| Layer | Component | Why Chosen | Alternatives |
|---|---|---|---|
| Storage | AWS S3 Standard | Fast setup, pay-as-you-go | MinIO (self), Yandex (EU) |
| Metadata DB | PostgreSQL 15 | FTS + JSONB, proven, no lock | MongoDB (schema-less), ClickHouse |
| Vector DB | Qdrant | 41 QPS @ 50M vectors, open-source | pgvector (<100K), Weaviate, Pinecone |
| Embeddings | all-MiniLM-L6-v2 | 384-dim, fast, good recall | all-mpnet (slower), OpenAI (cost) |
| PDF Extract | PyMuPDF | 2-3ร PDFMiner, accurate | pdfplumber, PDFMiner |
| LLM Enrichment | Claude 3.5 Haiku | Cheap (~$0.002/paper), accurate | GPT-4 (2ร cost), open-source models |
| Queue | Celery + Redis | Battle-tested, simple | Bull.js (Node), RabbitMQ |
| API | FastAPI | Async, auto-docs, Python | Flask (slower), Django (overkill) |
| CI/CD | GitHub Actions | Free, integrated | GitLab CI, Jenkins |
| Deployment | Docker + ECS | Container-native, scalable | Kubernetes (overkill for MVP) |
Cost Breakdown Per 100K Papers (Monthly)
Storage Layer: โจMATH:1โฉ0.023/GB + requests)
Metadata DB: $40 (RDS t3.medium: 1TB SSD)
Vector DB: $60 (EC2 t3.large: Qdrant)
Compute/Queue: $30 (EC2 t3.micro for workers)
Networking: $45 (NAT Gateway, S3 egress)
โโโโโโโโโโโโโโโโโโโโโโโโโโ
TOTAL: $222/mo
Breakdown per paper: $0.002/mo
Annual cost: $2,664 for 100K papers
Deployment Command
# Development
docker-compose up -d
# Production (AWS)
terraform apply # provision S3 + RDS + EC2
docker push my-registry/papers-api:latest
aws ecs update-service --cluster papers --service api --force-new-deployment