symfony/ai-typesense-store
Typesense vector store integration for Symfony AI Store, adding a fast, typo-tolerant search backend for storing and querying embeddings. Supports vector search via the Typesense API within your Symfony AI applications.
Architecture fit. This package is a bridge, not an application-facing library. It implements symfony/ai's StoreInterface over a Typesense collection, so the value to a Laravel codebase is that vector persistence becomes an injectable contract rather than a bespoke Typesense client. That is the right shape for us: StoreFactory (v0.11), clear() (v0.11), count() (v0.14), and VectorDocumentInterface (v0.14) mean the abstraction is converging on a stable seam. The catch is that Laravel is not Symfony — we get the Symfony components Laravel already vendors, but not the Symfony AI bundle wiring. We own the service provider, config, and container bindings.
Integration feasibility. Feasible for a scoped pilot, with two non-obvious prerequisites that must be checked before committing:
num_llm_* parameters. We must confirm whether the bridge creates collections or expects them pre-created with a matching schema — this determines whether we hand-roll Typesense admin code and where dimension mismatches will bite us during embedding-model upgrades.symfony/ai-typesense-store is one bridge in the symfony/ai monorepo; issues and PRs route to the parent repo. We need a concrete composer require set (symfony/ai-store + this bridge + a Typesense PHP client version constraint) validated against our PHP version before we quote effort.The API surface is small and the code path is direct (find, add, remove, clear, count), so a POC is days, not weeks. The surrounding work — ingestion pipeline, backfill, embedding versioning — is where the schedule actually lives.
Technical risk.
| Risk | Severity | Notes |
|---|---|---|
| Pre-1.0 churn | Medium | v0.14 with frequent minor bumps; VectorDocumentInterface and count both landed in 0.14. Pin exact versions, not ^. |
| Thin documentation | High | README is a stub plus links. No Laravel guidance, no failure-mode or config reference. Budget for source reading and possibly reading the parent monorepo tests. |
| Maturity signals | High | 0 stars, 0 dependents. Real adoption is unproven; the Symfony org backing is reassuring but this is not a battle-tested path. |
| Support model | Medium | MIT, community-only, no SLA. We are the escalation path. |
| Typesense operational load | Medium | Self-hosting means we own RAM sizing, replication, and upgrades; Typesense Cloud shifts this to a vendor cost. |
| Metadata drift | Low | Release metadata (a 2026-10-26 release date) is inconsistent; verify versions from the repo, not from the index. |
| Security posture | Positive | v0.10 hardened remove() against query injection in this and sibling bridges — early signs of security review. |
Key questions for the maintainers/our spike.
count() filter-aware, and is it cached/exposed in a way that is safe to call per request?add(), and is there batch ingestion support for backfills of 100K+ documents?symfony/ai minor is the hard floor, and what is the documented deprecation policy pre-1.0?Stack fit. Laravel 10+/PHP 8.2+ is a reasonable home: Laravel vendors Symfony components, StoreInterface maps cleanly to a container singleton, and Typesense is a plain HTTP service reachable from any Laravel runtime. There is no Laravel package, facade, or config stub shipped — we write roughly a service provider, a config/ai.php entry, and a thin repository wrapper. Expect ~1–3 engineer-days for the binding layer, plus real work on ingestion.
Two structural decisions belong to the TPM, not the engineer:
TypesenseStore leak into controllers. Bind StoreInterface behind our own VectorStore interface so a future swap (pgvector, Qdrant, Typesense Cloud) is a container change. v0.14's VectorDocumentInterface makes this cheap now; skipping it makes it expensive later.Migration path. Three entry points, in ascending cost:
count, filtering, and remove cover current usage before swapping. Anything using Typesense-specific features (faceting, curation, synonyms) likely stays on the raw client.Compatibility. Pin exact versions of both symfony/ai-store and the bridge; their minor releases move together and 0.x minors can carry interface additions. Validate that our Typesense server version supports the vector search API surface the bridge targets (docs reference 29.0). Confirm the PHP client library version the bridge pulls in does not conflict with anything already in composer.lock.
Sequencing.
add/find/remove/count, and error surfacing against a local Typesense container. Resolve the schema and multi-tenancy questions above. Output: go/no-go memo.count() for anything user-visible.Define the gate now: if the spike cannot answer schema provisioning and tenant-key isolation, we do not proceed to Week 2.
Maintenance. Low code surface, but a real upgrade treadmill: 0.x minor releases arrive frequently and 0.14 alone added an interface and a capability. Assign an owner, pin versions, and upgrade deliberately on a quarterly cadence with a regression suite around the store contract. Watch the parent symfony/ai monorepo, not the bridge repo, for changelogs and security notes.
Support. Community-only, MIT, no vendor SLA. Issues route to the main symfony/ai repository. Escalation is: we read the bridge source, then we patch locally via a Composer patch plugin if needed. That is acceptable for an internal search feature; it is not acceptable for a customer-facing SLA commitment without a fallback path. Keep the abstraction seam (see above) so a fork or replacement is contained.
Scaling. Sizing is a Typesense problem, not a PHP problem: the cluster is RAM-resident, so capacity planning is index-size-in-memory plus headroom for replication and future reindexes. Plan for two clusters' worth of RAM at the model-upgrade boundary, since a re-index into a new collection is the only safe way to swap embedding dimensions. On the Laravel side, watch queue depth on ingestion and search concurrency on the read path; both are ordinary Horizon/worker tuning.
Failure modes to instrument before launch:
count() against the source-table row count on a schedule.count() — treat as eventually consistent; never use it for billing-grade metering without reconciliation against an authoritative ledger.Ramp-up. The API learning curve is trivial — a mid-level Laravel engineer is productive in a day. The real ramp is Typesense operations (sizing, replication, snapshot/restore, upgrade procedure) and embedding-pipeline hygiene (batching, idempotency, model versioning). Budget one engineer for a week on Typesense ops before we own a production cluster, or buy Typesense Cloud and convert that cost into a line item. Given the package's 0-star, 0-dependent maturity, hedge by keeping the abstraction boundary strict and the pilot scoped to a single low-risk search surface — the migration cost of moving off it later should stay measured in days, not sprints.
How can I help you explore Laravel packages today?