Technology Stack
Complete inventory of technologies powering the AESOP platform, organized by architectural layer and service ownership.
Full Dependency Inventory
| Technology | Version | Service(s) | Purpose | Limitation / Note |
|---|---|---|---|---|
| PostgreSQL | 16.x | All | Primary relational database for all three services | Requires AGE and pgvector extensions compiled separately |
| Apache AGE | 1.5.x | All | Graph database extension for PostgreSQL; stores actor/relationship networks | Must match PostgreSQL major version; not available in managed cloud PostgreSQL |
| pgvector | 0.7.x | intell | Vector similarity search for semantic embeddings | IVFFlat index requires periodic retraining; HNSW index uses more memory |
| Redis | 7.x | All | Celery broker, cache backend, Channels layer | Single-threaded; large simulation payloads may bottleneck |
| MarkItDown | latest | intell | Converts uploaded documents (PDF, DOCX, PPTX) to Markdown for LLM ingestion | Microsoft library; quality varies by document complexity |
| Django | 5.1.x | All | Web framework, ORM, admin, authentication | Synchronous ORM; async views available but ORM calls still block |
| Django REST Framework | 3.15.x | All | REST API serialization, viewsets, inter-service HTTP calls | Adds overhead vs raw Django views for internal-only APIs |
| Django Channels | 4.x | simulation | WebSocket support for real-time simulation turn updates | Requires Daphne or uvicorn ASGI server instead of gunicorn |
| Daphne | 4.x | simulation | ASGI server for Django Channels WebSocket connections | Less battle-tested than gunicorn for pure HTTP workloads |
| Celery | 5.4.x | All | Distributed task queue: OSINT pipelines, propagation, turn execution | Task chains can stall if a worker crashes mid-chain; no built-in resumption |
| sentence-transformers | 3.x | intell | Generate text embeddings for semantic search and deduplication | Model loading is slow (~2s cold start); keep worker warm |
| NumPy / SciPy | 1.26.x / 1.13.x | simulation | Matrix operations for influence scoring and propagation calculations | Large matrices may require chunking for memory-constrained environments |
| Mistral AI | API | intell | LLM for entity extraction, summarization, and analytical briefs | Rate-limited; no local fallback; API costs scale with volume |
| Anthropic (Claude) | API | intell | Alternative LLM provider for analysis tasks | Same cloud-dependency constraints as Mistral |
| H3 | 4.x (h3-py) | All | Uber's hexagonal hierarchical spatial index; zone tiling and neighbor queries | Hex edges cause slight area distortion at poles; not an issue at operational latitudes |
| django-leaflet | 0.30.x | All | Django integration for Leaflet map widgets | Tightly coupled to Leaflet version; must keep in sync |
| Leaflet.js | 1.9.x | All | Interactive map rendering in the browser | Tile provider required (OpenStreetMap default); no offline mode without tile cache |
| HTMX | 2.x | All | Declarative AJAX: partial page updates without a JS framework | Complex client-side state (drag-and-drop, rich editors) still needs vanilla JS |
| Propagation Algorithms | custom | modelisation | Cascade influence propagation across graph networks | Custom implementation; no external library — must be maintained in-house |
Key Technology Choices
Why Apache AGE?
Apache AGE adds openCypher graph queries directly inside PostgreSQL. This eliminates the need for a separate Neo4j server, reducing operational complexity from two database engines to one. Actor networks, influence relationships, and faction hierarchies are modeled as graph vertices and edges while still joining against relational tables (scenarios, turns, zones) in the same transaction.
- + Single database process to operate, back up, and monitor
- + ACID transactions span both relational and graph data
- - Not available on managed PostgreSQL (AWS RDS, Cloud SQL)
- - Smaller ecosystem than Neo4j; fewer query optimizations
Why H3 Hexagonal Tiling?
Uber's H3 system tiles the globe into hexagonal cells at multiple resolutions. Unlike square grids, hexagons provide uniform adjacency (every cell has exactly 6 neighbors at equal distance), making influence propagation calculations symmetric and predictable.
- + Uniform area per cell — no latitude distortion like square grids
- + Built-in multi-resolution: zoom from country-level (res 3) to city-block (res 9)
- + Fast neighbor ring calculations via
h3.grid_ring() - ~ Pentagons exist at each resolution (12 total) but never at operational latitudes
Why Celery for Simulation?
The AESOP simulation engine runs in discrete turns, where each turn involves multiple sequential phases (OODA loop: Observe, Orient, Decide, Act). Celery task chains model this naturally: each phase is a task, chained so output flows to the next. Long-running propagation calculations execute on worker processes without blocking the Django web server.
- + Task chains model OODA phases as sequential steps
- + Horizontal scaling: add workers for heavier simulation loads
- + Redis broker shared with Django cache — no extra infrastructure
- - No built-in task resumption if a worker crashes mid-chain
Why HTMX over React?
AESOP's UI is server-rendered with Django templates. HTMX adds dynamic behavior (partial updates, form submissions, lazy loading) through HTML attributes rather than a JavaScript framework. This avoids a separate JS build pipeline, keeps the team in Python/Django, and reduces client-side complexity.
- + No Node.js, no webpack/vite, no npm dependencies
- + Django templates remain the single source of truth for UI
- + Progressive enhancement: pages work without JavaScript
- - Rich client interactions (map overlays, drag-drop) still need vanilla JS
Why Django Channels for Simulation?
The multiplayer simulation requires real-time push to all connected players when a turn resolves. HTTP polling would introduce latency and unnecessary load. Django Channels provides WebSocket support within the Django ecosystem, using the same authentication, middleware, and ORM. When a Celery task completes a turn, it publishes the result to a Channels group, and every connected player receives the update instantly.
- + Native Django integration — same auth, same session, same ORM
- + Channel groups map naturally to simulation rooms
- + Celery workers can publish directly to channel layers via Redis
- - Requires Daphne ASGI server instead of standard gunicorn
- - WebSocket connection scaling needs careful Redis channel-layer tuning