symfony/ai-surreal-db-message-store
SurrealDB message store integration for Symfony AI Chat, letting you persist and retrieve conversation messages in SurrealDB via its HTTP integration.
Architecture fit
This is a Symfony AI ecosystem component, not a Laravel package. It implements Symfony AI's message-store abstraction (MessageStoreInterface equivalent) backed by SurrealDB's HTTP API, and is published as a split read-only package from the symfony/ai monorepo. For a Laravel codebase the package is best understood as a reference implementation plus a portable interface contract, not a drop-in dependency. The good news, and the part often misjudged in early evaluations: Symfony components are generally Composer-installable inside Laravel (Laravel already ships HttpFoundation, Console, Process, Finder), so the technical constraint is not "Symfony code cannot run in Laravel." The constraint is container wiring, configuration shape, event semantics, and version pinning, all of which are adapter-level work rather than architectural conflict.
The real architectural question is SurrealDB, not Symfony. SurrealDB earns its place only if the product genuinely needs flexible/document-hybrid message records (embeddings, sentiment, tool-call payloads, per-message metadata that would otherwise become JSON columns or EAV tables), or sub-second reactive reads. If the chat history is a straightforward append-only log with a handful of columns, Postgres with jsonb plus an Eloquent model will be cheaper to own and better supported by the existing team.
Integration feasibility Feasible with a thin Laravel adapter, in the region of one to three engineering weeks for an experienced PHP engineer, contingent on:
MessageRepository), so application code never references the Symfony type directly.symfony/ai — a classic source of transitive resolution conflicts alongside Laravel's own pins.Technical risk Rated medium-high, primarily supply-chain and maturity risk rather than capability risk:
Key questions
jsonb sufficient and materially cheaper?Stack fit The realistic path is an adapter, not a fork and not a microservice. Concretely:
SurrealMessageStore class implementing a Laravel-defined contract.Http client for the actual transport rather than Symfony's HttpClient, to inherit Laravel's retry, timeout, and Http::fake() testing ergonomics. If the package's concrete class is used directly, wrap it and treat Symfony's HTTP exceptions as an implementation detail translated to Laravel exceptions.config/ai.php (or config/chat.php), following Laravel's publishable-config convention.MessageStored, ConversationRetrieved) at the adapter boundary; do not attempt to bridge Symfony's dispatcher into Illuminate\Contracts\Events\Dispatcher.Migration path
Http client, confirm UUID fidelity and ordering semantics. Gate: messages round-trip without corruption.MessageRepository (append, listByConversation, deleteConversation) in the Laravel app. Every later decision is reversible behind this interface.Compatibility
symfony/ai constraint graph resolves against the app's existing Symfony component versions; this is the most likely early blocker and should be checked in hour one, not week two.messages, conversations) and indexes must be provisioned explicitly — Laravel migrations do not apply. Track them as versioned .surql files in the repo with an idempotent bootstrap command, or you will have an untracked schema drift problem.Http::fake() fixtures around the SurrealDB payloads so the suite runs without a live database.Sequencing
Deliver the contract and adapter first, feature-flag second, dual-write third, cutover last. Do not let SurrealDB adoption ride on the first AI feature launch; the AI chat feature should ship on the safer store if there is any schedule pressure, with the SurrealDB path as a follow-on optimization. If the team cannot commit to owning the .surql schema files and the auth header design in sprint one, stop and keep the incumbent store.
Maintenance Two maintenance surfaces exist: the dependency (pre-1.0, monorepo-lockstep releases, 0 dependents) and the SurrealDB instance. Budget for a quarterly dependency review, and expect at least one breaking change per year while the package is pre-1.0. Keeping the Laravel-owned interface small is the mitigation — it caps blast radius to a single class. Forking is explicitly discouraged: a fork of a monorepo split package re-created on every upstream commit is a permanent tax with no offsetting benefit here.
Support
No vendor support; upstream is a community/Symfony org GitHub issue tracker, and issues are filed against the parent symfony/ai repo, not this package. Internal ownership must be named — a specific engineer or team accountable for the adapter and the schema. SurrealDB itself needs an owner for upgrades, backup verification, and access control. Document the adapter as internal infrastructure with a runbook; treat it as critical path once chat history is user-visible.
Scaling HTTP-per-operation introduces per-message latency in the tens of milliseconds, and chat persistence is write-heavy and bursty (a single turn may produce several records). Design for batching writes per turn and paginating reads by conversation with a cursor; avoid unbounded history fetches. Validate against a realistic target — for example, p95 under 100ms for a 20-message append with 3 concurrent turns — before committing. Connection pooling is not available over plain HTTP, so throughput scales with SurrealDB's HTTP endpoint capacity and the PHP worker pool, not with Laravel's queue unless writes are explicitly pushed to jobs. Consider queueing non-blocking writes if the user-facing latency budget is tight.
Failure modes
.surql bootstrap and a CI check.composer update pulls an incompatible symfony/ai and breaks the adapter at runtime. Mitigate with lockfile discipline and a smoke test in CI.Ramp-up Expect two to four days of engineer ramp-up: one day on SurrealDB fundamentals (SurrealQL, the namespace/database/record model, HTTP endpoints), one day on the Symfony AI message-store contract, and one to two days reproducing and testing the payloads. Do not assume Laravel familiarity covers SurrealDB — the query language and auth model are genuinely different. If no one on the team has SurrealDB experience, add a formal learning allocation to the spike, and treat "we'll pick it up" as a schedule risk rather than a plan.
How can I help you explore Laravel packages today?