๐—ฆ๐˜๐—ผ๐—ฝ ๐—™๐—ผ๐—ฟ๐—ฐ๐—ถ๐—ป๐—ด ๐—š๐—ฟ๐—ฎ๐—ฝ๐—ต ๐—ค๐˜‚๐—ฒ๐—ฟ๐—ถ๐—ฒ๐˜€ ๐—œ๐—ป๐˜๐—ผ ๐—ฅ๐—ฒ๐—น๐—ฎ๐˜๐—ถ๐—ผ๐—ป๐—ฎ๐—น ๐——๐—ฎ๐˜๐—ฎ๐—ฏ๐—ฎ๐˜€๐—ฒ๐˜€

Our recommendation logic used to be a 280-line SQLite query with six self-joins.

We wanted to answer one question: what should a user watch next?

To do this, we had to find videos watched by people who watched the current video. We also needed to factor in recency and region.

The real problem was the engine. We tried to force a graph problem through a relational model.

The results were poor:

Recommendations are inherently a graph problem. Users, videos, creators, and tags are nodes. Actions like "watched" or "tagged" are edges.

We moved this subsystem to SurrealDB. We kept the rest of our stack on PHP 8.4 and SQLite.

The results changed immediately:

How it works:

In SQL, you need multiple joins through a "watches" table. In a graph database, you use a single traversal. The edges are the index.

SurrealDB allows us to:

We also simplified our privacy approach. We do not store personal identifiers on the graph. We use rotating session tokens with a hard expiration. This follows the principle of data minimization.

The technical takeaway:

If you have a query that uses many joins to follow relationships, you are modeling a graph problem relationally. You pay for that mismatch on every single page view.

Do not try to optimize a bad model in place. Isolate that specific subsystem, reshape it as a graph, and watch your latency drop.

Source: https://dev.to/ahmet_gedik778845/using-surrealdb-graph-queries-to-power-video-recommendations-303c