StackDependenciesNumPy

NumPy

Last updated: Aug 28, 2026


Rationale

NumPy is the fundamental package for scientific and numerical computing in Python. In matches, we use it to perform exact in-memory cosine similarity search correlating unstructured threat descriptions against our catalog of vulnerability criteria definitions.

The main reasons why we chose it over dedicated vector databases are:

  • It is open source.
  • It is already a core, pinned dependency across our Python stack, requiring zero additional packages, native wheel compilations, or foreign runtime bridges.
  • For our criteria dataset (~147 parent definitions, ~600 KB in float32 embeddings), exact matrix multiplication (np.dot) executes in tens of microseconds using hardware-accelerated BLAS and SIMD vectorization.
  • It provides 100% exact recall with zero approximation error, graph truncation, or quantization distortion inherent in HNSW or IVF-PQ index structures.
  • It simplifies data serialization and storage: the entire criteria index persists as a single compact .npz file, enabling sub-50ms cold starts in ephemeral AWS Batch workers without multi-file directory extraction.
  • Read-only in-memory arrays support concurrent access across all worker threads without connection pooling, SQLite file locks, or IPC overhead.
  • It completely eliminates supply-chain risks and maintenance overhead associated with third-party vector database engines.

Alternatives

ChromaDB

ChromaDB was initially adopted as a prototype in matches.

  • It accumulated four high- and critical-severity CVEs (CVE-2026-45829, CVE-2026-45830, CVE-2026-45833, and CVE-2026-45832) covering remote code execution, unauthenticated collection mutation, and RBAC authorization bypasses.
  • These vulnerabilities were unreachable in our execution model: matches runs ChromaDB strictly in embedded mode (PersistentClient), exposes no HTTP endpoints, computes embeddings externally via Voyage AI, and executes inside single-tenant batch jobs.
  • However, upstream maintainers demonstrated inadequate security governance: they left coordinated vulnerability disclosures unacknowledged for months, applied incomplete patches that fixed the Rust backend while leaving the Python server vulnerable (issue #7588), and provided no patched release (<= 1.5.9).
  • It introduced 33 unused transitive dependencies (~45 MB of wheels) into the build graph, including onnxruntime, kubernetes, grpcio, uvicorn, fastapi, and pypika (which required custom Nix patching).

LanceDB

LanceDB is an embedded, serverless vector database built in Rust on Apache Arrow.

  • It provides columnar storage, disk-backed indexing (IVF-PQ), and full-text hybrid search capabilities.
  • However, for a static dataset of ~147 criteria vectors, introducing LanceDB adds external dependency weight (lancedb, pylance, PyArrow version pinning) and multi-file directory structures that are unnecessary when exact BLAS matrix operations in NumPy run faster and with zero additional dependencies.

SciPy

SciPy is a scientific computation library providing spatial distance functions via scipy.spatial.distance.cdist.

  • It provides built-in cosine distance calculations (cdist(..., metric='cosine')).
  • However, its general-purpose C loop calculates vector norms dynamically on every query, making it 2x to 5x slower than multiplying pre-normalized matrices with BLAS np.dot.
  • It introduces 30 to 50 MB of compiled shared libraries (Fortran routines, LAPACK wrappers, optimization solvers) that are entirely unused by vector similarity search.

scikit-learn

scikit-learn is a machine learning library offering nearest-neighbor search algorithms via NearestNeighbors and cosine_similarity.

  • Its pairwise cosine similarity functions act as a Python-level wrapper around the same underlying np.dot call, adding array validation and intermediate memory allocations without algorithmic performance gains.
  • It introduces a large dependency footprint (30 to 60 MB of wheels) and increases cold-start import latency in ephemeral batch containers.

Usage

We use NumPy in matches for:

  • Storing 1024-dimensional Voyage AI (voyage-3) embedding matrices for Fluid Attacks' vulnerability criteria definitions (fa_defines_collection).
  • Computing exact top-k cosine similarity via vector-matrix dot products (np.dot) against threat descriptions extracted from customer documentation.
  • Serving as the in-memory similarity search engine in ephemeral AWS Batch workers, loading .npz snapshots from Amazon S3 with sub-millisecond query latency prior to LLM-as-judge refinement.

On this page