{
  "source_file": "0930",
  "source_platform": "个人博客",
  "author": "Eugene Yan",
  "title_listed": "System Design for Recommendations and Search",
  "keywords": "系统设计,推荐,搜索",
  "domain": "机器学习",
  "content_type": "深度技术解析",
  "is_paid_flag": "否",
  "url": "https://eugeneyan.com/writing/system-design-for-discovery/",
  "publish_date": "2021-07",
  "corpus_stage": "推理部署",
  "notes": "推荐与搜索系统设计",
  "id": "8dcc97f36ba3",
  "collected_at": "2026-10-02T14:16:53",
  "title": "System Design for Recommendations and Search",
  "body_markdown": "eugeneyan\nStart Here\nWriting\nSpeaking\nPrototyping\nAbout\nSystem Design for Recommendations and Search\n[\nteardown\nproduction\nengineering\nrecsys\n🔥\n]\n· 13 min read\nAlso translated to\nKorean\nthanks to Zimin Park.\nHow do the system designs for industrial recommendations and search look like? It’s uncommon to see system design discussed in machine learning papers or blogs; most focus on model design, training data, and/or loss functions. Nonetheless, the handful of papers that discuss implementation details elucidate design patterns and best practices that are hard to gain outside of hands-on experience.\nSpecific to discovery systems (i.e., recommendations and search), most implementations I’ve come across follow a similar paradigm—components and processes are split into offline vs. online environments, and candidate retrieval vs. ranking steps. The 2 x 2 below tries to simplify this.\n2 x 2 of online vs. offline environments, and candidate retrieval vs. ranking.\nThe offline environment\nlargely hosts batch processes such as model training (e.g., representation learning, ranking), creating embeddings for catalog items, and building an approximate nearest neighbors (ANN) index or knowledge graph to find similar items. It may also include loading item and user data into a feature store that is used to augment input data during ranking.\nThe online environment\nthen uses the artifacts generated (e.g., ANN indices, knowledge graphs, models, feature stores) to serve individual requests. A typical approach is converting the input item or search query into an embedding, followed by candidate retrieval and ranking. There are also other preprocessing steps (e.g., standardizing queries, tokenization, spell check) and post-processing steps (e.g., filtering undesirable items, business logic) though we won’t discuss them in this writeup.\nCandidate retrieval\nis a fast—but coarse—step to narrow down millions of items into hundreds of candidates. We trade off precision for efficiency to quickly narrow the search space (e.g., from millions to hundreds, a 99.99% reduction) for the downstream ranking task. Most contemporary retrieval methods convert the input (i.e., item, search query) into an embedding before using ANN to find similar items. Nonetheless, in the examples below, we’ll also see systems using graphs (DoorDash) and decision trees (LinkedIn).\nRanking\nis a slower—but more precise—step to score and rank top candidates. As we’re processing fewer items (i.e., hundreds instead of millions), we have room to add features that would have been infeasible in the retrieval step (due to compute and latency constraints). Such features include item and user data, and contextual information. We can also use more sophisticated models with more layers and parameters.\nRanking can be modeled as a learning-to-rank or classification task, with the latter being more commonly seen. If deep learning is applied, the final output layer is either a softmax over a catalog of items, or a sigmoid predicting the likelihood of user interaction (e.g., click, purchase) for each user-item pair.\nNext, let’s see how the processes above come together in a recommender or search system.\nBasic system design for recommendations and search, based on the 2 x 2 above.\nIn the offline environment, data flows bottom-up,\nwhere we use training data and item/user data to create artifacts such as models, ANN indices, and feature stores. These artifacts are then loaded into the online environment (via the dashed arrows).\nIn the online environment, each request flows left to right,\nthrough the retrieval and ranking steps before returning a set of results (e.g., recommendations, search results).\nAdditional details on some arrows in the diagram:\nWith the trained representation learning model, embed items in the catalog.\nWith the item embeddings, build the ANN index that allows retrieval of similar embeddings and their respective items.\nGet (historical) features to augment training data for the ranking model. Use the same feature store in offline training and online serving to minimize train-serve skew. Might require\ntime travel\n.\nUse the input query/item(s) embedding to retrieve\nk\nsimilar items via ANN.\nAdd item and user features to the candidates for downstream ranking.\nRank the candidates based on objectives such as click, conversion, etc.\nUpdate: This 2x2 has since been referenced in other resources, including:\nNVIDIA’s “\nRecommender Systems, Not Just Recommender Models\n”\nXavier Amatriain’s “\nBlueprints for RecSys Architectures\n”\nExamples from Alibaba, Facebook, JD, Doordash, etc.\nNext, we’ll briefly discuss the high-level system design of some discovery systems, based on their respective papers and tech blogs. I’ll highlight how these systems are split into offline and online environments, and their retrieval and ranking steps. For full details on the methodology, model, etc., I recommend you read the full paper/blog.\nWe start with Alibaba’s sharing about\nbuilding item embeddings for candidate retrieval\n.\nIn the\noffline\nenvironment, session-level user-item interactions are mined to construct a weighted, bidirectional item graph. The graph is then used to generate item sequences via random walks. Item embeddings are then learned via representation learning (i.e., word2vec skip-gram), doing away with the need for labels. Finally, with the item embeddings, they get the nearest neighbor for each item and store it in their item-to-item (i2) similarity map (i.e., a key-value store).\nAlibaba's design for candidate retrieval in Taobao via item embeddings and ANN.\nIn the\nonline\nenvironment, when the user launches the app, the\nTaobao\nPersonalization Platform (TPP) starts by fetching the latest items that the user interacted with (e.g., click, like, purchase). These items are then used to\nretrieve\ncandidates from the i2i similarity map. The candidates are then passed to the Ranking Service Platform (RSP) for\nranking\nvia a deep neural network, before being displayed to the user.\nAlibaba also shared a similar example where they apply a\ngraph network for ranking\n.\nIn the\noffline\nenvironment, they combine an existing knowledge graph (\nG\n), user behavior (e.g., impressed but not clicked, clicked), and item data to create an adaptive knowledge graph (\nG_ui\n). This is then merged with user data (e.g., demographics, user-item preferences) to train the ranking model (Adaptive Target-Behavior Relational Graph Network, ATBRN).\nAlibaba's design for ranking in Taobao via a graph network (ATBRN).\nIn the\nonline\nenvironment, given a user request, the candidate generator\nretrieves\na set of candidates and the user ID, before passing them to the Real-Time Prediction (RTP) platform. RTP then queries the knowledge graph and feature stores for item and user attributes. The graph representations, item data, and user data is then fed into the\nranking\nmodel (i.e., ATBRN) to predict the probability of click on each candidate item. The candidates are then reordered based on probability and displayed to the user.\nNext, we look at Facebook’s\nembedding-based retrieval for search\n.\nIn the\noffline\nenvironment (right half of image), they first train a two-tower network—with a query encoder and document encoder—that outputs cosine similarity for each query-document pair (not shown in image). This ensures that search queries and documents (e.g., user profiles, groups) are in the same embedding space.\nFacebook's design for embedding-based retrieval via query and document encoders.\nThen, with the document encoder, they embed each document via Spark batch jobs. The embeddings are then quantized and published into their ANN index (“inverted index”). This ANN index is based on\nFaiss\nand fine-tuned (see Section 4.1 of paper). The embeddings are also published in a forward index, without quantization, for ranking. The forward index can also include other data such as profile and group attributes to augment candidates during ranking.\nIn the\nonline\nenvironment, each search request goes through query understanding and is embedded via the query encoder. The search request and associated embedding then go through the\nretrieval\nstep to get nearest neighbor candidates via the ANN index and boolean filtering (e.g., match on name, location, etc.). The candidates are then augmented with full embeddings and additional data from the forward index before being\nranked\n.\nJD shared a similar approach for\nsemantic retrieval for search\n.\nIn the\noffline\nenvironment, a two-tower model with a query encoder and an item encoder is trained to output a similarity score for each query-item pair. The item encoder then embeds catalog items before loading them into an embedding index (i.e., key-value store).\nMajor stages of an e-commerce search systems (left), JD's design for candidate retrieval (right).\nThen, in the\nonline\nenvironment, each query goes through preprocessing (e.g., spelling correction, tokenization, expansion, and rewriting) before being embedding via the query encoder. The query embedding is then used to\nretrieve\ncandidates from the embedding index via nearest neighbors lookup. The candidates are then\nranked\non factors such as relevance, predicted conversion, etc.\nThe paper also shares practical tips to optimize model training and serving. For model training, they raised that the de facto input of user-item interaction, item data, and user data is duplicative—item and user data appear once per row, consuming significant disk space. To address this, they built a custom TensorFlow dataset where user and item data are first loaded into memory as lookup dictionaries. Then, during training, these dictionaries are queried to append user and item attributes to the training set. This simple practice reduced training data size by 90%.\nThey also called out the importance of ensuring offline training and online serving consistency. For their system, the most critical step was text tokenization which happens thrice (data preprocessing, training, serving). To minimize train-serve skew, they built a C++ tokenizer with a thin Python wrapper that was used for all tokenization tasks.\nFor model serving, they shared how they reduced latency by combining services. Their model had two key steps: query embedding and ANN lookup. The simple approach would be to have each as a separate service, but this would require two network calls and thus double network latency. Thus, they unified the query embedding model and ANN lookup in a single instance, where the query embedding is passed to the ANN via memory instead of network.\nThey also shared how they run hundreds of models simultaneously, for different retrieval tasks and various A/B tests. Each “servable” consists of a query embedding model and an ANN lookup, requiring 10s of GB. Thus, each servable had their own instance, with a proxy module (or load balancer) to direct incoming requests to the right servable.\nHow JD organizes the embedding model and ANN indices across multiple versions.\n(Aside: My candidate retrieval systems have a similar design pattern. Embedding stores and ANN indices are hosted on the same docker container—you’ll be surprised how far this goes with efficiently-sized embeddings. Furthermore, Docker makes it easy to version, deploy, and roll back each model, as well as scale horizontally. Fronting the model instances with a load balancer takes care of directing incoming requests,\nblue-green deployments\n, and\nA/B testing\n. SageMaker makes this easy.)\nNext, we move from the embedding + ANN paradigm and look at DoorDash’s use of a\nknowledge graph for query expansion and retrieval\n.\nIn the\noffline\nenvironment, they train models for query understanding, query expansion, and ranking. They also load documents (i.e., restaurants and food items) into ElasticSearch for use in retrieval, and attribute data (e.g., ratings, price points, tags) into a feature store.\nDoorDash splits search into offline and online, and retrieval (recall) and ranking (precision).\nIn the\nonline\nenvironment, each incoming query is first standardized (e.g., spell check) and synonymized (via a manually curated dictionary). Then, the knowledge graph (Neo4J)\nexpands the query\nby finding related tags. For example, a query for “KFC” will return tags such as “fried chicken” and “wings”. These tags are then used to\nretrieve\nsimilar restaurants such as “Popeyes” and “Bonchon”.\nThese candidates are then\nranked\nbased on lexical similarity between the query and documents (aka restaurants, food items), store popularity, and possibly the search context (e.g., time of day, location). Finally, the ranked results are augmented with attributes such as ratings, price point, and delivery time and cost before displayed to the customer.\nFinally, we look at how LinkedIn\npersonalizes talent search results\n.\nTheir system relies heavily on XGBoost, first as a model to retrieve the top 1,000 candidates for ranking, and second, as a generator of features (i.e., model scores, tree interactions) for their downstream ranking model (a generalized linear mixed model aka GLMix).\nLinkedIn's offline design for generating tree-based features, and training GLMix ranking models.\nIn the\noffline\nenvironment,  they first combine impression and label data to generate training data (step 1 in image above). Labels consist of instances where the recruiter sent a message to potential hires and the user responded positively. The training data is then fed into a pre-trained XGBoost model to generate model scores and tree interaction features (step 3 in image above) to augment the training data. This augmented data is then used to train the ranking model (GLMix).\nLinkedIn's online design for candidate retrieval, feature augmentation, and ranking via GLMix.\nIn the\nonline\nenvironment, with each search request, the search engine (maybe Elastic or Solr?) first\nretrieves\ncandidates which are then scored via a first-level XGBoost model. The top 1,000 candidates are then augmented with (i) additional features (step 2 in image above) and (ii) tree interaction features via a second-level XGBoost model (step 3 in image above). Finally, these augmented candidates are ranked before the top 125 results are shown to the user.\nConclusion\nThat was a brief overview of the offline-online, retrieval-ranking pattern for search and recommendations. While this isn’t the only approach for discovery systems, from what I’ve seen, it’s the most common design pattern. I’ve found it helpful to distinguish the latency-constrained online systems from the less-demanding offline systems, and split the online process into retrieval and ranking steps.\nIf you’re starting to build your discovery system, start with\ncandidate retrieval via simple embeddings and approximate nearest neighbors\n, before adding a ranker on top of it. Alternatively, consider using a knowledge graph\nlike Uber and DoorDash did\n. But before you get too excited, think hard about whether you need real-time retrieval and ranking, or\nif batch recommendations will suffice\n.\nDid I miss out anything? Please reach out and let me know!\nLet's explore how recsys & search are often split into:\n• Latency-constrained online vs. less-demanding offline environments\n• Fast but coarse candidate retrieval vs. slower and more precise ranking\nExamples from Alibaba, Facebook, JD, DoorDash, etc.\nhttps://t.co/zTsfElLw1z\n— Eugene Yan (@eugeneyan)\nJune 30, 2021\nUpdate (2022-04-14): Even Oldridge and Karl Byleen-Higley from NVIDIA updated the\n2-stage design to 4-stages\nby adding a filtering step and splitting ranking into scoring and ordering. They also presented it at\nKDD’s Industrial Recommender Systems workshop\n.\nEven Oldridge & Karl Byleen-Higley (NVIDIA) augmented my 2-stage design with 2 more stages.\nReferences\nBillion-scale Commodity Embedding for E-commerce Recommendation\nAlibaba\nAdaptive Target-Behavior Relational Graph Network for Recommendation\nAlibaba\nEmbedding-based Retrieval in Facebook Search\nFacebook\nAn End-to-End Solution for E-commerce Search via Embedding Learning\nJD\nThings Not Strings: Understanding Search Intent with Better Recall\nDoorDash\nEntity Personalized Talent Search Models with Tree Interaction Features\nLinkedIn\nFaiss: A Library for Efficient Similarity Search\nFacebook\nThanks\nto Yang Xinyi for reading drafts of this.\nIf you found this useful, please cite this write-up as:\nYan, Ziyou. (Jun 2021). System Design for Recommendations and Search. eugeneyan.com.\n        https://eugeneyan.com/writing/system-design-for-discovery/.\nor\n@article{yan2021system,\n  title   = {System Design for Recommendations and Search},\n  author  = {Yan, Ziyou},\n  journal = {eugeneyan.com},\n  year    = {2021},\n  month   = {Jun},\n  url     = {https://eugeneyan.com/writing/system-design-for-discovery/}\n}\nShare on:\nBrowse related tags:\n[\nteardown\nproduction\nengineering\nrecsys\n🔥\n]\nor\nSearch\n« Patterns for Personalization in Recommendations and Search\nInfluencing without Authority for Data Scientists »\nJoin\n11,800+\nreaders getting updates on machine learning, RecSys, LLMs, and engineering.\nGet email updates",
  "metadata": {
    "title": "System Design for Recommendations and Search",
    "description": "Breaking it into offline vs. online environments, and candidate retrieval vs. ranking steps.",
    "keywords": null,
    "author": "Eugene Yan",
    "og:site_name": "eugeneyan.com",
    "og:title": "System Design for Recommendations and Search",
    "og:type": "article",
    "og:description": "Breaking it into offline vs. online environments, and candidate retrieval vs. ranking steps.",
    "og:url": "https://eugeneyan.com/writing/system-design-for-discovery/",
    "og:image": "https://eugeneyan.com/assets/og_image/discovery-2x2-v2.jpg",
    "twitter:card": "summary_large_image",
    "twitter:domain": "eugeneyan.com",
    "twitter:title": "System Design for Recommendations and Search",
    "twitter:description": "Breaking it into offline vs. online environments, and candidate retrieval vs. ranking steps.",
    "twitter:image": "https://eugeneyan.com/assets/og_image/discovery-2x2-v2.jpg",
    "article:published_time": "2021-06-27T00:00:00+00:00",
    "article:author": "https://eugeneyan.com/about/",
    "article:section": "posts",
    "article:tag": "🔥"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/8dcc97f36ba3/code/body-000.txt",
      "chars": 252,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/icon-search.svg",
      "bytes": 425,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-feeb4bd87b8704a903b2.svg",
      "src": "https://eugeneyan.com/assets/icon-search.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/discovery-2x2.webp",
      "bytes": 13602,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-7eba34d6428b2b884cfd.webp",
      "src": "https://eugeneyan.com/assets/discovery-2x2.webp",
      "alt": "2x2 of online vs. offline environments, and candidate retrieval vs. ranking.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/discovery-system-design.webp",
      "bytes": 25720,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-3691bbee06959c3fd06c.webp",
      "src": "https://eugeneyan.com/assets/discovery-system-design.webp",
      "alt": "Basic system design of a recommender or search system.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/alibaba-retrieval-design.webp",
      "bytes": 22442,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-881d411d4b475db5daea.webp",
      "src": "https://eugeneyan.com/assets/alibaba-retrieval-design.webp",
      "alt": "Alibaba's design for candidate retrieval in Taobao.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/alibaba-ranking-design.webp",
      "bytes": 45770,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-c2140f93d3331a4f4333.webp",
      "src": "https://eugeneyan.com/assets/alibaba-ranking-design.webp",
      "alt": "Alibaba's design for ranking in Taobao.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/facebook-retrieval-design.webp",
      "bytes": 46258,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-ca416c83aba923750950.webp",
      "src": "https://eugeneyan.com/assets/facebook-retrieval-design.webp",
      "alt": "Facebook's design for embedding-based retrieval.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/jd-retrieval-design.webp",
      "bytes": 33994,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-aea1e73cda0186a175f0.webp",
      "src": "https://eugeneyan.com/assets/jd-retrieval-design.webp",
      "alt": "Major stages of an e-commerce search systems (left), JD's design for candidate retrieval (right).",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/jd-model-server.webp",
      "bytes": 21968,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-89e153c1331fae1b52c8.webp",
      "src": "https://eugeneyan.com/assets/jd-model-server.webp",
      "alt": "How JD organizes the embedding model and ANN indices across multiple versions.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/doordash-search-design.webp",
      "bytes": 24128,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-a7b7e1b9e8c29c391361.webp",
      "src": "https://eugeneyan.com/assets/doordash-search-design.webp",
      "alt": "How DoorDash splits their search into offline and online, and retrieval (recall) and ranking (precision)",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/linkedin-offline-design.webp",
      "bytes": 25724,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-28c963cd1c466d3a69fe.webp",
      "src": "https://eugeneyan.com/assets/linkedin-offline-design.webp",
      "alt": "LinkedIn's offline design for generating GLMix ranking models.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/linkedin-online-design.webp",
      "bytes": 32908,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-b3f5bcd785e98cb5ecef.webp",
      "src": "https://eugeneyan.com/assets/linkedin-online-design.webp",
      "alt": "LinkedIn's online design for candidate retrieval, feature augmentation, and ranking via GLMix.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/4-stage-recsys.webp",
      "bytes": 49966,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-da9154ef534a6a5fdb72.webp",
      "src": "https://eugeneyan.com/assets/4-stage-recsys.webp",
      "alt": "NVIDIA augmented the 2-stage design with 2 more stages.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/icon-twitter.svg",
      "bytes": 892,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-0083a7581b07e5f40e7b.svg",
      "src": "https://eugeneyan.com/assets/icon-twitter.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/icon-linkedin.svg",
      "bytes": 559,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-f7a16c3e46e5838cec4d.svg",
      "src": "https://eugeneyan.com/assets/icon-linkedin.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/bluesky.svg",
      "bytes": 745,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-be754e8ecdaf6de94f55.svg",
      "src": "https://eugeneyan.com/assets/bluesky.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/icon-facebook.svg",
      "bytes": 1123,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-5d55b59733923cf14223.svg",
      "src": "https://eugeneyan.com/assets/icon-facebook.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://eugeneyan.com/assets/icon-mail.svg",
      "bytes": 841,
      "reused": false,
      "local_path": "attachments/8dcc97f36ba3/images/body-b179147617228dfafb9f.svg",
      "src": "https://eugeneyan.com/assets/icon-mail.svg",
      "alt": "",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [
    {
      "url": "https://www.youtube.com/watch?v=5qjiY-kLwFY",
      "src": "https://www.youtube.com/watch?v=5qjiY-kLwFY&list=PL65MqKWg6XcrdN4TJV0K1PdLhF_Uq-b43&index=4",
      "status": "download_failed",
      "kind": "single_video",
      "error": "ERROR: [youtube] 5qjiY-kLwFY: This video is unavailable\n",
      "title": "",
      "retried_at": "2026-10-20T22:23:38Z"
    }
  ],
  "links": [
    {
      "href": "https://eugeneyan.com/",
      "label": "eugeneyan",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/start-here/",
      "label": "Start Here",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/writing/",
      "label": "Writing",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/speaking/",
      "label": "Speaking",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/prototyping/",
      "label": "Prototyping",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/about/",
      "label": "About",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/search/",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/tag/teardown/",
      "label": "teardown",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/tag/production/",
      "label": "production",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/tag/engineering/",
      "label": "engineering",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/tag/recsys/",
      "label": "recsys",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/tag/🔥/",
      "label": "🔥",
      "type": "a"
    },
    {
      "href": "https://ziminpark.github.io/posts/system-design-for-discovery/",
      "label": "Korean",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/writing/feature-stores/",
      "label": "time travel",
      "type": "a"
    },
    {
      "href": "https://medium.com/nvidia-merlin/recommender-systems-not-just-recommender-models-485c161c755e",
      "label": "Recommender Systems, Not Just Recommender Models",
      "type": "a"
    },
    {
      "href": "https://amatriain.net/blog/RecsysArchitectures",
      "label": "Blueprints for RecSys Architectures",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/1803.02349",
      "label": "building item embeddings for candidate retrieval",
      "type": "a"
    },
    {
      "href": "https://taobao.com/",
      "label": "Taobao",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/2005.12002",
      "label": "graph network for ranking",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/2006.11632",
      "label": "embedding-based retrieval for search",
      "type": "a"
    },
    {
      "href": "https://engineering.fb.com/2017/03/29/data-infrastructure/faiss-a-library-for-efficient-similarity-search/",
      "label": "Faiss",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/2006.02282",
      "label": "semantic retrieval for search",
      "type": "a"
    },
    {
      "href": "https://docs.aws.amazon.com/wellarchitected/latest/machine-learning-lens/bluegreen-deployments.html",
      "label": "blue-green deployments",
      "type": "a"
    },
    {
      "href": "https://docs.aws.amazon.com/sagemaker/latest/dg/model-ab-testing.html",
      "label": "A/B testing",
      "type": "a"
    },
    {
      "href": "https://doordash.engineering/2020/12/15/understanding-search-intent-with-better-recall/",
      "label": "knowledge graph for query expansion and retrieval",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/writing/search-query-matching/",
      "label": "expands the query",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/1902.09041",
      "label": "personalizes talent search results",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/writing/real-time-recommendations/",
      "label": "candidate retrieval via simple embeddings and approximate nearest neighbors",
      "type": "a"
    },
    {
      "href": "https://t.co/zTsfElLw1z",
      "label": "https://t.co/zTsfElLw1z",
      "type": "a"
    },
    {
      "href": "https://twitter.com/eugeneyan/status/1410029817496576009?ref_src=twsrc%5Etfw",
      "label": "June 30, 2021",
      "type": "a"
    },
    {
      "href": "https://www.youtube.com/watch?v=5qjiY-kLwFY&list=PL65MqKWg6XcrdN4TJV0K1PdLhF_Uq-b43&index=4",
      "label": "KDD’s Industrial Recommender Systems workshop",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/writing/patterns-for-personalization/",
      "label": "« Patterns for Personalization in Recommendations and Search",
      "type": "a"
    },
    {
      "href": "https://eugeneyan.com/writing/influencing-without-authority/",
      "label": "Influencing without Authority for Data Scientists »",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:52:16Z",
  "source_url": "https://eugeneyan.com/writing/system-design-for-discovery/",
  "papers": [
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1803.02349",
      "bytes": 2971166,
      "reused": false,
      "local_path": "papers/repair/3f46e0176c41018652f3.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/2005.12002",
      "bytes": 5072682,
      "reused": false,
      "local_path": "papers/repair/58ff60f4c224e97eb8d4.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/2006.11632",
      "bytes": 868336,
      "reused": false,
      "local_path": "papers/repair/a4df419b898afe1f50a0.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/2006.02282",
      "bytes": 3112295,
      "reused": false,
      "local_path": "papers/repair/cd9428cc4301d92a5e7f.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1902.09041",
      "bytes": 606503,
      "reused": false,
      "local_path": "papers/repair/beb6fc51345712512d11.pdf"
    }
  ],
  "actual_video_files": [],
  "body_chars": 17070,
  "expected_body_images": 17,
  "discovery_status": "ok",
  "delivery_status": "partial",
  "missing_reason": "download_failed",
  "raw_html": "attachments/8dcc97f36ba3/pages/source.html",
  "local_html": "attachments/8dcc97f36ba3/pages/article.html",
  "body_base_path": "attachments/8dcc97f36ba3/pages/",
  "body_markdown_path": "attachments/8dcc97f36ba3/pages/article.md"
}