Two-Tower and FAISS: AI Recommendation System for Personalization

A catalog with thousands of items loses sales when every shopper sees the same feed. We design and implement end-to-end recommendation systems: we understand your data, train the model, and hand it over to your team with retraining policies. Personalization helps grow repeat purchase share and average order value without expanding the assortment.
Frequently Asked Questions

Why a catalog doesn't sell: building a recommendation system

A catalog with hundreds of thousands of items loses not on assortment but on output. A new visitor and a returning customer see the same first screen: the same categories, the same collections, the same order of cards.

Card conversion drops not because of the product, but because it's shown to someone who isn't ready to buy.

As long as catalog personalization rests on manual rules, its ceiling is set by their number. Rules stack up, conflict with each other, and every change requires a release.

After fifty conditions, no one can say why a particular card ended up first, and testing a new hypothesis stretches over weeks.

At the same time, the system holds unused behavioral data: views, search queries, favorites, time on a card, bounces after a click. That's a ready signal of intent, but it doesn't affect output — at most it goes into a report. A vicious circle: weak output yields few clicks, and the model can't learn on weak data.

The working scheme is a two-tower model (Two-Tower): one part computes a customer vector from their history, the other computes an item vector from attributes and text.

Both vectors live in the same space, so output is assembled not by scanning the catalog but by finding the nearest items via FAISS.

This matching fits within the page response budget and is recalculated on fresh events rather than once a day. Manual rules remain the top layer: promos, stop-lists and stock limit the model's output rather than replace it.

Below we break down how this is covered: from signal collection and model validation to quality control and rollback to the previous version.

What changes after implementation: impact in measurable metrics

Personalization shifts metrics not through cosmetic interface tweaks but through a change in ranking logic. Previously, output order was built on popularity and freshness — everyone got the same one.

After implementation, each user sees a sequence computed for their history, so the share of target actions grows without traffic growth.

Technically, two towers do the work: one computes a user representation, the other computes an item representation.

Proximity is found via vector search over a FAISS index, from which a short candidate list is taken and then re-ranked taking into account stock, delivery and catalog constraints.

Output response time is maintained through precomputation: representations are updated on events, not at request time. The storefront serves ready-made blocks from cache, so its load drops — instead of heavy queries on every impression, short key-based reads do the work.

A whole class of failures that used to break output is removed separately: cold start for a new user, a spike during a sale, an item with no history. For such cases there's a fallback — popular within the segment, limiting the candidate pool, gradual retraining.

The personalization effect becomes predictable: the share of target actions and session depth grow, output response time stays steady under load, and the storefront stops being a bottleneck.

Comparing recommendation approaches: rules, models, hybrid

Each output scheme wins on its own data profile and breaks on someone else's.

Manual rules and a popular block give a predictable launch but don't account for a specific user's interest; collaborative filtering relies on the behavior of similar users and requires a dense event stream; content-based features work from the description of the item itself and don't depend on history.

In practice, three things determine the choice: how many interactions have been accumulated, how fast the catalog updates, and how critical cold start is.

Approach When it fits Limitations
Rules and a popular block Launching from scratch, rare events, need for explainable output Doesn't personalize, quickly hits the engagement ceiling
Collaborative filtering There's interaction history and a stable event stream New users and new items get no output until they accumulate data
Content-based features Rich catalog description, frequent assortment changes Shows what's similar to what's already been viewed, doesn't go beyond established taste
Hybrid scheme A production loop with heterogeneous traffic and a resilience requirement More expensive to maintain: feature recalculation, labeling, output quality control

A hybrid is usually assembled not "all at once" but layer by layer: the collaborative signal handles the main output, content-based features back up new items, and rules constrain undesirable combinations.

We start with a data audit and a quality metric — only after that do we lock in the scheme, otherwise comparing approaches remains theoretical.

Implementation stages: from data audit to model handover

Building a recommendation system starts not with the model but with data: each next step relies on the previous one being verified. First we count which signals are missing for personalization, and only then do we lock in the scheme. This order saves weeks of rework.

Implementation route

  1. Data audit. We look at the composition of events, history depth, the share of anonymous sessions and the sparsity of interactions across the catalog. We record which signals are missing and what needs to be added to log collection.
  2. Solution scheme. We split the system into two loops: fast candidate selection from the entire catalog and precise ranking of the selected items by user and item features. Here we also define the feature list and their update frequency.
  3. Output setup. We assemble training pairs from history, balance popular and new items, and add exclusion rules: already purchased, stock constraints, brand exclusions.
  4. Quality validation. We evaluate on a time-held-out segment rather than a random sample — otherwise metrics are inflated. Then we move part of the traffic to the new output and compare with a control group.
  5. Solution handover. We hand over loop configurations, the feature schema, the retraining policy and the procedure for rollback to the previous output version. We train the team and stay in touch during the period of independent operation.

Handover artifacts: schemes, configurations, retraining policies

We hand over not a "turnkey working service" but a kit your team can use to maintain the system without us: launch it, retrain it, roll it back, extend the features. Below is what physically remains in the repository and the knowledge base after delivery.

  • Integration schemes — where the recommendation service connects: receiving the catalog and user profile, serving the list to the frontend and to mailings, timeouts and behavior when a data source is unavailable.

  • Training and serving configurations — model parameters, representation dimensions, candidate selection and re-ranking rules. All in configuration files, not in code: changing settings doesn't require a release.

  • Retraining policy — triggers (on schedule, on an influx of new items, on a metric drop), the run order, acceptance criteria for a new version and the procedure for returning to the previous one.

  • Access separation — roles for training data, for the serving service and for launching retraining, who is authorized to roll out a model, action logging.

  • Solution documentation — architecture, feature dictionary, purpose of components, known limitations and workarounds for each.

  • A set of checks — offline quality metrics, control samples, tests for cold start and for a drop in interest in an item.

  • In-production monitoring — which indicators are collected continuously, trigger thresholds, the points where you look for the cause of a discrepancy between training and serving.

  • Operating instructions — bringing it up from scratch, rebuilding the vector index, recovery after a failure, typical requests and answers to them.

We verify each item at acceptance: your engineers walk through it by hand and confirm that the scheme is readable, the configuration launches, and the policy is clear without a call to us.

Case study: personalizing output in a marketplace catalog

The catalog has hundreds of thousands of items, and output rested on rules: popularity, freshness, stock. A buyer got the same order regardless of what they had viewed and purchased before, so the first screens were occupied by items outside their interest.

Transitions to the target action barely grew along with traffic — the bottleneck was not the assortment but how it was presented.

We built a two-tower model: one part encodes the user by viewing and order history, the other encodes the item by attributes and texts. Proximity is computed via a vector index, FAISS, so the personalized order is built on the fly rather than by a nightly recalculation.

On top of the scoring we left re-ranking: stock, delivery terms and margin still decide what makes it to the top.

What the measurements showed

Metric Before After
Output order unified, rule-based personalized for logged-in users
Transitions to the target action from the feed baseline +27% on comparable traffic
Session depth 4 cards 6.4 cards
Output response during peak hours dips steady, four times faster
New item in the feed only by general rules included within minutes

We tested resilience separately: when the model is unavailable, output rolls back to the previous rules, and the catalog doesn't end up empty. Repeat measurements a month later held at the same level — the growth came from personalization, not a seasonal wave.

What to do when there's almost no training data: cold start

When data is scarce, cold start isn't the absence of logs altogether but a lack of history for a specific user or item. A new visitor arrives without a profile, a new item without impressions, a young project without accumulated interactions.

The matrix formally exists but is sparse: almost all "user–item" pairs are empty, and the model learns the catalog average.

We build the first loop not on behavior but on content: items and users are described by features — category, brand, attributes, description text, the composition of the current session.

From these, vectors are assembled on which a two-tower model is trained: one tower encodes the user, the other the item, and proximity is found via vector search. Such a loop converges on tens of thousands of events.

Next comes output warm-up: we don't wait for a full history but gradually mix behavior into content. The weight of the behavioral part grows with the number of interactions of the user and the item, so a fresh profile doesn't outweigh statistics on similar ones.

We allocate part of the impressions to exploration — deliberately diverse output to collect feedback on unexplored items.

We separate weak signals by confidence levels: impression, click, full view, add to list. They can't be dumped into a single counter — a random impression would start counting as interest, so each level is assigned a weight.

Cold start is closed not when the model has trained but when the share of personalized slots in output grows, catalog coverage expands, and a new user gets a relevant impression in fewer steps.

That's why we keep the content loop as a permanent layer rather than a placeholder until logs accumulate.

Addressing doubts: data quality, load, support

We check data quality before training, not after. We filter the event log for duplicates, bots and anomalous spikes; we don't delete broken records but flag them: they show where event transmission from the frontend is lost.

The result is a reproducible set on which metrics are comparable between runs and don't "drift" from run to run.

We calculate load in advance: recommendation matching is served by a separate service, and profile recalculation and vector search don't compete with the main database for resources.

Nearest-representation search on FAISS runs in memory, so output fits within the overall page response budget, and as the catalog grows it scales by adding nodes without rewriting the logic.

What if there's little data at the start?

For the first weeks the system runs on content features and similarity rules — they provide meaningful output without user history. Then the weight gradually shifts to behavioral signals as events accumulate, and cold start stops being a bottleneck.

How do you notice quality degradation?

On a control slice we compute the share of successful interactions and catalog coverage; a drop below the threshold raises an alert.

The model doesn't "drift" unnoticed: the previous snapshot is saved, and rolling back to it takes minutes rather than a separate training cycle.

Will we be able to retrain the model ourselves?

We hand over the retraining policy, data preparation scripts and a shadow-traffic check before rollout — retraining becomes a routine procedure rather than a one-off. We describe model maintenance in the documentation so your engineer can handle it.

Let's discuss your task: what data and access are needed for an estimate

To come back with a quote rather than clarifying questions, we need access to actual data: it shows whether there's enough history to train the model or whether it first has to be accumulated. Below is the minimum set that covers this stage.

  • An export of events for 3–6 months: views, search queries, add-to-cart, purchases — with user ID, item ID and timestamp.
  • The catalog schema: attributes, categories, stock, availability, relationships between items.
  • Test read-only access to the catalog and orders API — we'll check the completeness of history and event frequency.
  • An infrastructure description: where you plan to compute recommendations — in your own environment or in the cloud, and which network access is needed for that.
  • A role matrix: who on the business side approves the data composition and who is responsible for rollout on your systems' side.
  • Current metrics: purchase conversion, repeat order share, session depth — the baseline against which we'll compare the result.
  • Constraints: what is prohibited from use (personal data, payment information), retention requirements.

After that we calculate the sample size, check the data for sparsity and gaps, and then send an implementation plan: stages, control points and the effect you'll see at each of them.

AI Development Areas

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1393
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1368
  • B2B Advance company logo design
    B2B Advance company logo design
    815
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1139
  • AIDER company logo development
    AIDER company logo development
    1057
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1152