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
.npzfile, 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
matches previously used ChromaDB for vector similarity search. Although the
disclosed ChromaDB CVEs were unreachable in our embedded runtime, upstream
maintenance issues, unaddressed disclosures, and dependency bloat required
replacing it with pure NumPy.
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:
matchesruns 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, andpypika(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.dotcall, 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
.npzsnapshots from Amazon S3 with sub-millisecond query latency prior to LLM-as-judge refinement.