Что такое связывание профилей
Связывание профилей позволяет объединить ваши учётные записи из разных социальных сетей в единую карточку в результатах поиска Яндекса.
Зачем это нужно
- Люди, которые ищут вас, увидят все ваши профили в одном месте
- Вы сможете контролировать, какая информация отображается в поисковой выдаче
- Поисковая система точнее определит, что все профили принадлежат одному человеку
Быстрый старт
Время выполнения: 5 минут
Рекомендуемый способ
- Откройте страницу управления внешними аккаунтами в Яндекс ID
- Выберите социальную сеть из списка
- Войдите в свой профиль в выбранной сети
- Подтвердите разрешение на использование данных о связях
- Повторите для всех профилей, которые нужно связать
Примечание
Изменения вступят в силу в течение 24–72 часов после обновления поискового индекса. Точное время зависит от приоритета индексации вашего профиля.
Поддерживаемые социальные сети
| Социальная сеть |
Через Яндекс ID |
Взаимные ссылки |
| ВКонтакте |
Да |
Да |
| Одноклассники |
Да |
Нет |
| LiveJournal |
Нет |
Да |
| Facebook (Meta) |
Да |
Да |
| X (Twitter) |
Да |
Да |
| LinkedIn |
Да |
Да |
Частые вопросы
Когда профили объединятся
Обычно в течение 24–72 часов после добавления ссылок или связывания через Яндекс ID. Точное время зависит от частоты индексации вашего профиля поисковым роботом.
Можно ли отменить связывание
Да. Откройте настройки внешних аккаунтов в Яндекс ID и удалите нужный профиль из списка. Дополнительная информация доступна в справке Яндекс ID.
Что делать, если профили не связались
Проверьте следующее:
- Прошло ли 72 часа с момента добавления ссылок
- Доступны ли ваши профили для просмотра без авторизации (публичные настройки)
- Правильно ли указаны URL в настройках профилей
- Находятся ли ссылки в разделах «Контакты» или «О себе», а не в постах
What is profile linking
Profile linking allows you to merge your accounts from different social networks into a single card in Yandex search results.
Why you need it
- People searching for you will see all your profiles in one place
- You can control what information appears in search results
- The search engine will more accurately determine that all profiles belong to one person
Quick start
Time required: 5 minutes
Recommended method
- Open external accounts management page in Yandex ID
- Click "Add account" button
- Select a social network from the list
- Log into your profile in the selected network
- Confirm permission to use connection data
- Repeat for all profiles you want to link
Note
Changes will take effect within 24–72 hours after the search index is updated. The exact time depends on your profile's indexing priority.
Supported social networks
| Social Network |
Via Yandex ID |
Mutual Links |
| VKontakte |
Yes |
Yes |
| Odnoklassniki |
Yes |
No |
| LiveJournal |
No |
Yes |
| Facebook (Meta) |
Yes |
Yes |
| X (Twitter) |
Yes |
Yes |
| LinkedIn |
Yes |
Yes |
Frequently asked questions
When will profiles be merged
Usually within 24–72 hours after adding links or connecting via Yandex ID. The exact time depends on your profile's indexing frequency by the search robot.
Can I cancel the linking
Yes. Open external accounts settings in Yandex ID and remove the desired profile from the list. Additional information is available in Yandex ID help.
What if profiles don't link
Check the following:
- Have 72 hours passed since adding links
- Are your profiles available for viewing without authorization (public settings)
- Are URLs correctly specified in profile settings
- Are links located in "Contacts" or "About" sections, not in posts
Обзор системы
Назначение
Функция связывания профилей предназначена для агрегации и унификации данных о пользователе из различных открытых источников (социальные сети, блоги, публичные профили) в единый консолидированный профиль. Основной задачей является группировка (кластеризация) профилей, принадлежащих одному физическому лицу, для повышения релевантности поисковой выдачи.
Терминология
| Термин |
Определение |
| Профиль |
Отдельная учётная запись пользователя в социальной сети или на публичном ресурсе. |
| Группа (Кластер) |
Набор Профилей, которые алгоритмически или явно связаны с одним и тем же пользователем. |
| Связь |
Ссылка (URL) из Профиля A на Профиль B, используемая как метаданные для алгоритма группировки. |
| Индексация |
Процесс обхода и анализа Профилей поисковым роботом для обновления данных в Кластере. |
Границы сервиса
Что входит в сервис
- Автоматическое обнаружение и связывание профилей при соблюдении условий
- Отображение связанных профилей в результатах поиска Яндекса
- Управление связями через интерфейс Яндекс ID
Что не входит в сервис
- Синхронизация данных между социальными сетями
- Единый вход (SSO) во все связанные сервисы
- Объединение списков контактов или публикуемого контента
Быстрый старт
| Целевая аудитория |
Пользователи с базовыми техническими навыками |
| Время выполнения |
5–10 минут |
| Предварительные условия |
Активные профили минимум в двух социальных сетях |
Приоритетный метод: Централизованное управление
Наиболее эффективный способ управления связями — использование централизованного сервиса Яндекс ID, который позволяет подтвердить принадлежность профилей через OAuth-авторизацию.
- Перейдите на страницу управления внешними аккаунтами
- Выполните аутентификацию в Яндекс ID (или создайте аккаунт)
- В блоке «Социальные сети» нажмите кнопку «Добавить аккаунт»
- Выберите целевую социальную сеть из выпадающего списка
- Авторизуйтесь во всплывающем окне выбранной сети
- Подтвердите предоставление разрешений на доступ к публичным данным профиля
- Повторите шаги 3–6 для каждого профиля
Техническая справка
Связывание происходит на стороне сервера Яндекса. Время вступления изменений в силу составляет 24–72 часа (медианное значение: 48 часов) и зависит от приоритета индексации.
Дополнительная информация: Справка Яндекс ID — Социальные сети
Методы связывания
Метод 1: Централизованное управление через Яндекс ID
| Сложность |
Низкая |
| Поддерживаемые сети |
Все основные платформы (ВКонтакте, Одноклассники, Facebook, X, LinkedIn) |
| Требования |
Аккаунт Яндекса |
Преимущества:
- Единая точка управления всеми связями
- Не требуется редактирование профилей в социальных сетях
- Поддержка OAuth 2.0 для безопасной авторизации
- Подходит для сетей с ограниченными возможностями ручной настройки (например, Одноклассники)
Метод 2: Взаимные ссылки в профилях
| Сложность |
Средняя |
| Поддерживаемые сети |
ВКонтакте, LiveJournal, личные сайты |
| Требования |
Права на редактирование обоих профилей |
Определение
Взаимная связь (двусторонняя) — это ситуация, при которой Профиль A содержит ссылку на Профиль B в своих настройках, и Профиль B содержит ссылку на Профиль A.
Инструкции по платформам
| Социальная сеть |
Раздел конфигурации |
Требуемое действие |
| ВКонтакте |
Редактирование → Контакты
vk.com/edit?act=contacts |
Добавить URL целевого профиля в поле Личный сайт или через Интеграция с другими сервисами. |
| LiveJournal |
Настройки → Способы связи (External services) |
Добавить URL целевых профилей. |
Важно
Взаимная связь является наиболее надёжным и приоритетным сигналом для алгоритма. Ссылки должны быть размещены в структурированных полях профиля (разделы «Контакты», «О себе»), а не в текстовых постах или комментариях.
Метод 3: Подтверждённая связь (OAuth)
| Сложность |
Низкая |
| Поддерживаемые сети |
Сети с официальными интеграциями (Facebook, X, LinkedIn) |
| Требования |
Поддержка OAuth в обеих сетях |
Определение
Подтверждённая связь (односторонняя) — это связь, при которой Профиль A содержит ссылку на Профиль B, и эта связь была установлена с использованием механизма подтверждения (через OAuth-авторизацию или ввод учётных данных Профиля B).
Справочная информация
Матрица совместимости методов
| Социальная сеть |
Яндекс ID |
Взаимные ссылки |
OAuth-интеграция |
| ВКонтакте |
Да |
Да |
Нет |
| Одноклассники |
Да |
Нет |
Нет |
| LiveJournal |
Нет |
Да |
Нет |
| Facebook (Meta) |
Да |
Да |
Да |
| X (Twitter) |
Да |
Да |
Да |
| LinkedIn |
Да |
Да |
Да |
Технические характеристики
| Параметр |
Значение |
Примечание |
| Время индексации |
24–72 часа |
Зависит от приоритета индексации профиля |
| Максимум профилей в кластере |
20 |
Превышение может указывать на ошибку алгоритма |
| Глубина проверки ссылок |
1 уровень |
Транзитивные связи не обрабатываются автоматически |
| Частота переиндексации |
7–30 дней |
Зависит от активности профиля и изменений в данных |
| Срок действия связи |
Бессрочно |
До момента удаления ссылки или отзыва разрешений |
Уровни сервиса (SLA)
| Метрика |
Целевое значение |
| Доступность API Яндекс ID |
99.9% (до 43 минут простоя в месяц) |
| Скорость обработки запросов |
< 500 мс (95-й перцентиль) |
| Время отображения в поиске |
До 72 часов после индексации |
| Техническая поддержка |
Понедельник–Воскресенье, 24/7 через форму обратной связи |
Логика алгоритма
Условия формирования связи
Профиль A и Профиль B будут объединены в один Кластер, если выполняется одно из следующих условий:
- Взаимная связь (двусторонняя): Профиль A содержит ссылку на Профиль B, и Профиль B содержит ссылку на Профиль A.
- Подтверждённая связь (односторонняя): Профиль A содержит ссылку на Профиль B, и эта связь была установлена с использованием механизма подтверждения (например, через OAuth-авторизацию или ввод учётных данных Профиля B).
- Яндекс ID: Оба профиля добавлены в один аккаунт Яндекса через интерфейс управления внешними аккаунтами.
Процесс обнаружения связей
- Индексация профиля
Поисковый робот выполняет плановую индексацию профиля в социальной сети.
- Извлечение метаданных
Система анализирует структурированные поля: «Контакты», «О себе», «Сайты».
- Идентификация URL
Обнаруженные URL нормализуются и классифицируются по типу социальной сети.
- Проверка взаимности
Для каждого найденного Профиля B система проверяет наличие обратной ссылки на Профиль A.
- Валидация подтверждения
Для OAuth-ссылок выполняется запрос статуса к API социальной сети.
- Формирование кластера
Связанные профили объединяются в группу с присвоением уникального идентификатора.
- Обновление индекса
Кластер профилей сохраняется в поисковом индексе для отображения в результатах.
Приоритеты методов связывания
При обнаружении нескольких методов связывания система применяет следующий приоритет:
| Приоритет |
Метод |
Уровень доверия |
| 1 (наивысший) |
Яндекс ID |
Высокий (явное подтверждение пользователя) |
| 2 |
Подтверждённая связь (OAuth) |
Высокий (авторизация через OAuth) |
| 3 |
Взаимная связь |
Средний (косвенное подтверждение) |
Устранение проблем
Проблема: Профили не связываются после 72 часов
Диагностика
- Проверка доступности профиля
Откройте профиль в режиме инкогнито браузера (без авторизации). Если ссылки не видны — они недоступны поисковому роботу.
- Проверка взаимности
Убедитесь, что ссылка присутствует в обоих направлениях: A → B и B → A.
- Проверка расположения ссылки
Ссылки должны быть в структурированных полях профиля (разделы «Контакты», «О себе»), а не в постах или комментариях.
Решение
- Измените настройки приватности профиля на «Публичный» или «Открытый»
- Переместите ссылки в разделы «Контакты» или «О себе»
- Дождитесь следующего цикла индексации (до 30 дней для низкоприоритетных профилей)
- Как альтернатива: используйте Яндекс ID для явного связывания
Проблема: Связались профили разных людей
Возможные причины
- Ошибка алгоритма при совпадении имени, фотографии и других метаданных
- Третье лицо намеренно добавило ссылку на ваш профиль в свой профиль
Решение
- Откройте страницу управления внешними аккаунтами в Яндекс ID
- Удалите некорректный профиль из списка связанных аккаунтов
- Если профиль не отображается в списке, обратитесь в службу поддержки через форму обратной связи
Как разорвать связь между профилями
Способ 1: Через Яндекс ID (рекомендуется)
- Перейдите на страницу управления внешними аккаунтами
- Найдите профиль, который нужно отвязать
- Нажмите кнопку «Удалить» или иконку удаления рядом с профилем
- Подтвердите действие
Способ 2: Удаление ссылок из профилей
- Откройте настройки профиля в социальной сети
- Удалите ссылку на другой профиль из соответствующего раздела
- Сохраните изменения
- Повторите для второго профиля (если использовались взаимные ссылки)
Следствие
Внесённые изменения будут учтены при ближайшем цикле индексации. Сроки обновления зависят от частоты обхода ресурса поисковым роботом (обычно 24–72 часа).
Глоссарий
| Термин |
Определение |
| Связывание профилей |
Процесс объединения нескольких учётных записей в единую сущность в поисковом индексе для формирования консолидированной карточки в результатах поиска. |
| Профиль |
Отдельная учётная запись пользователя в социальной сети или на публичном ресурсе. |
| Группа (Кластер) |
Набор профилей, которые алгоритмически или явно связаны с одним и тем же пользователем. |
| Взаимная связь |
Двунаправленная связь между профилями: Профиль A ссылается на Профиль B, и Профиль B ссылается на Профиль A. |
| Подтверждённая связь |
Связь, установленная через официальный механизм интеграции социальной сети, требующий аутентификации (OAuth). |
| Индексация |
Процесс обхода и анализа профилей поисковым роботом для обновления данных в кластере. |
| Публичный профиль |
Профиль в социальной сети, доступный для просмотра без аутентификации. |
Обратная связь и поддержка
Каналы связи
System overview
Purpose
The profile linking feature is designed to aggregate and unify user data from various open sources (social networks, blogs, public profiles) into a single consolidated profile. The main objective is to group (cluster) profiles belonging to the same person to improve search relevance.
Terminology
| Term |
Definition |
| Profile |
A separate user account on a social network or public resource. |
| Group (Cluster) |
A set of Profiles that are algorithmically or explicitly linked to the same user. |
| Link |
A URL reference from Profile A to Profile B, used as metadata for the grouping algorithm. |
| Indexing |
The process of crawling and analyzing Profiles by the search robot to update data in the Cluster. |
Service boundaries
What is included
- Automatic discovery and linking of profiles when conditions are met
- Display of linked profiles in Yandex search results
- Link management through Yandex ID interface
What is not included
- Data synchronization between social networks
- Single sign-on (SSO) across all linked services
- Merging of contact lists or published content
Quick start
| Target audience |
Users with basic technical skills |
| Time required |
5–10 minutes |
| Prerequisites |
Active profiles in at least two social networks |
Priority method: Centralized management
The most effective way to manage links is using the centralized Yandex ID service, which allows confirming profile ownership through OAuth authorization.
- Navigate to external accounts management page
- Authenticate in Yandex ID (or create an account)
- In the "Social Networks" block, click "Add account"
- Select the target social network from the dropdown list
- Authorize in the popup window of the selected network
- Confirm granting permissions to access public profile data
- Repeat steps 3–6 for each profile
Technical Reference
Linking occurs on Yandex's server side. Changes take effect within 24–72 hours (median: 48 hours) depending on indexing priority.
Additional information: Yandex ID Help — Social Networks
Linking methods
Method 1: Centralized management via Yandex ID
| Complexity |
Low |
| Supported networks |
All major platforms (VKontakte, Odnoklassniki, Facebook, X, LinkedIn) |
| Requirements |
Yandex account |
Advantages:
- Single management point for all links
- No need to edit profiles in social networks
- OAuth 2.0 support for secure authorization
- Suitable for networks with limited manual configuration options (e.g., Odnoklassniki)
Method 2: Mutual links in profiles
| Complexity |
Medium |
| Supported networks |
VKontakte, LiveJournal, personal websites |
| Requirements |
Edit permissions for both profiles |
Definition
Mutual link (bidirectional) is a situation where Profile A contains a link to Profile B in its settings, and Profile B contains a link to Profile A.
Platform-specific instructions
| Social Network |
Configuration Section |
Required Action |
| VKontakte |
Edit → Contacts
vk.com/edit?act=contacts |
Add target profile URL in Personal website field or via Integration with other services. |
| LiveJournal |
Settings → Contact methods (External services) |
Add target profile URLs. |
Important
Mutual link is the most reliable and priority signal for the algorithm. Links must be placed in structured profile fields (sections "Contacts", "About"), not in text posts or comments.
Method 3: Confirmed link (OAuth)
| Complexity |
Low |
| Supported networks |
Networks with official integrations (Facebook, X, LinkedIn) |
| Requirements |
OAuth support in both networks |
Definition
Confirmed link (unidirectional) is a connection where Profile A contains a link to Profile B, and this link was established using a confirmation mechanism (via OAuth authorization or entering Profile B credentials).
Reference information
Method compatibility matrix
| Social Network |
Yandex ID |
Mutual Links |
OAuth Integration |
| VKontakte |
Yes |
Yes |
No |
| Odnoklassniki |
Yes |
No |
No |
| LiveJournal |
No |
Yes |
No |
| Facebook (Meta) |
Yes |
Yes |
Yes |
| X (Twitter) |
Yes |
Yes |
Yes |
| LinkedIn |
Yes |
Yes |
Yes |
Technical specifications
| Parameter |
Value |
Note |
| Indexing time |
24–72 hours |
Depends on profile indexing priority |
| Maximum profiles per cluster |
20 |
Exceeding may indicate algorithm error |
| Link verification depth |
1 level |
Transitive links are not automatically processed |
| Reindexing frequency |
7–30 days |
Depends on profile activity and data changes |
| Link validity period |
Indefinite |
Until link removal or permission revocation |
Service level (SLA)
| Metric |
Target Value |
| Yandex ID API availability |
99.9% (up to 43 minutes downtime per month) |
| Request processing speed |
< 500 ms (95th percentile) |
| Time to appear in search |
Up to 72 hours after indexing |
| Technical support |
Monday–Sunday, 24/7 via feedback form |
Algorithm logic
Link formation conditions
Profile A and Profile B will be merged into one Cluster if at least one of the following conditions is met:
- Mutual link (bidirectional): Profile A contains a link to Profile B, and Profile B contains a link to Profile A.
- Confirmed link (unidirectional): Profile A contains a link to Profile B, and this link was established using a confirmation mechanism (e.g., via OAuth authorization or entering Profile B credentials).
- Yandex ID: Both profiles are added to one Yandex account through the external accounts management interface.
Link discovery process
- Profile indexing
The search robot performs scheduled indexing of the profile on the social network.
- Metadata extraction
The system analyzes structured fields: "Contacts", "About", "Websites".
- URL identification
Discovered URLs are normalized and classified by social network type.
- Reciprocity verification
For each found Profile B, the system checks for a back link to Profile A.
- Confirmation validation
For OAuth links, a status request is made to the social network API.
- Cluster formation
Linked profiles are grouped with a unique identifier assigned.
- Index update
The profile cluster is saved in the search index for display in results.
Linking method priorities
When multiple linking methods are detected, the system applies the following priority:
| Priority |
Method |
Trust Level |
| 1 (highest) |
Yandex ID |
High (explicit user confirmation) |
| 2 |
Confirmed link (OAuth) |
High (OAuth authorization) |
| 3 |
Mutual link |
Medium (indirect confirmation) |
Troubleshooting
Problem: Profiles don't link after 72 hours
Diagnostics
- Check profile availability
Open the profile in browser incognito mode (without authorization). If links are not visible — they are unavailable to the search robot.
- Check reciprocity
Ensure the link exists in both directions: A → B and B → A.
- Check link location
Links must be in structured profile fields (sections "Contacts", "About"), not in posts or comments.
Solution
- Change profile privacy settings to "Public" or "Open"
- Move links to "Contacts" or "About" sections
- Wait for the next indexing cycle (up to 30 days for low-priority profiles)
- Alternative: use Yandex ID for explicit linking
Problem: Profiles of different people linked
Possible causes
- Algorithm error with matching name, photo, and other metadata
- Third party intentionally added a link to your profile in their profile
Solution
- Open external accounts management page in Yandex ID
- Remove the incorrect profile from the linked accounts list
- If the profile is not displayed in the list, contact support via feedback form
How to break the link between profiles
Method 1: Via Yandex ID (recommended)
- Navigate to external accounts management page
- Find the profile you want to unlink
- Click "Remove" button or delete icon next to the profile
- Confirm the action
Method 2: Removing links from profiles
- Open profile settings in the social network
- Remove the link to another profile from the corresponding section
- Save changes
- Repeat for the second profile (if mutual links were used)
Consequence
Changes will be taken into account during the next indexing cycle. Update time depends on the resource crawl frequency by the search robot (usually 24–72 hours).
Glossary
| Term |
Definition |
| Profile linking |
The process of merging multiple accounts into a single entity in the search index to form a consolidated card in search results. |
| Profile |
A separate user account on a social network or public resource. |
| Group (Cluster) |
A set of profiles that are algorithmically or explicitly linked to the same user. |
| Mutual link |
Bidirectional connection between profiles: Profile A links to Profile B, and Profile B links to Profile A. |
| Confirmed link |
A connection established through the official social network integration mechanism requiring authentication (OAuth). |
| Indexing |
The process of crawling and analyzing profiles by the search robot to update data in the cluster. |
| Public profile |
A social network profile available for viewing without authentication. |
Feedback and support
Contact channels
Технический обзор
Назначение сервиса
Profile Grouping Service (PGS) — это микросервис, ответственный за обнаружение, валидацию и агрегацию связей между пользовательскими профилями в различных социальных сетях для формирования консолидированного представления в поисковом индексе Яндекса.
Владельцы и контакты
| Роль |
Команда / Лицо |
Контакт |
| Service Owner |
Команда поисковых сервисов |
search-team@yandex-team.ru |
| Tech Lead |
Иванов И.И. |
ivanov@yandex-team.ru |
| On-call Engineer |
Rotation schedule |
Slack: #search-oncall |
Зоны ответственности
- Обработка событий от Яндекс ID при добавлении/удалении социальных связей
- Парсинг структурированных данных из профилей социальных сетей
- Валидация взаимных ссылок между профилями
- Интеграция с OAuth API социальных сетей для проверки подтверждённых ссылок
- Формирование и обновление кластеров профилей
- Публикация событий изменения кластеров в шину данных
Что не входит в зону ответственности
- Индексация контента социальных сетей (ответственность: Indexing Pipeline)
- Хранение и управление учётными записями Яндекс ID (ответственность: Passport Service)
- Отображение результатов в поисковой выдаче (ответственность: SERP Service)
Архитектура системы
Компоненты
| Компонент |
Технология |
Назначение |
pgs-api |
Python 3.11, FastAPI |
REST API для управления связями профилей |
pgs-worker |
Python 3.11, Celery |
Асинхронная обработка задач связывания и валидации |
pgs-crawler |
Go 1.21 |
Парсинг профилей социальных сетей и извлечение метаданных |
pgs-validator |
Python 3.11 |
Валидация взаимных ссылок и проверка подтверждений |
Зависимости от внешних систем
| Система |
Назначение |
Критичность |
| Passport Service |
Аутентификация, события добавления профилей |
Критичная |
| Indexing Pipeline |
Данные о профилях из поискового индекса |
Критичная |
| Social API Gateway |
Проксирование запросов к API социальных сетей |
Высокая |
| PostgreSQL |
Хранение кластеров, профилей и связей |
Критичная |
| Redis |
Кэширование, rate limiting |
Средняя |
| Kafka |
Шина событий для межсервисной коммуникации |
Высокая |
Топология развёртывания
[Passport Service]
|
| (Kafka event: profile.linked)
v
[pgs-worker] --> [pgs-validator] --> [pgs-crawler]
| |
v v
[PostgreSQL] [Social API Gateway]
|
v
[Kafka event: cluster.updated] --> [Indexing Pipeline]
API и интеграции
REST API эндпоинты
| Метод |
Путь |
Описание |
Аутентификация |
| GET |
/api/v1/clusters/:user_id |
Получить кластер профилей пользователя |
OAuth token |
| POST |
/api/v1/links |
Добавить связь между профилями |
OAuth token |
| DELETE |
/api/v1/links/:link_id |
Удалить связь по идентификатору |
OAuth token |
| POST |
/api/v1/clusters/reindex |
Принудительная переиндексация кластера |
Service token |
Пример запроса
POST /api/v1/links HTTP/1.1
Host: pgs.yandex.net
Authorization: OAuth ya29.a0AfH6SMBx...
Content-Type: application/json
{
"source_profile_id": "vk:12345678",
"target_profile_url": "https://www.facebook.com/john.doe",
"link_type": "manual"
}
Пример ответа (успех)
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/links/lnk_9a8b7c6d5e4f
{
"link_id": "lnk_9a8b7c6d5e4f",
"status": "pending_validation",
"created_at": "2025-11-03T14:23:45Z",
"estimated_processing_time": "48h"
}
Коды ответов HTTP
| Код |
Значение |
Описание |
Действие клиента |
| 200 |
OK |
Запрос выполнен успешно |
Обработать ответ |
| 201 |
Created |
Связь создана |
Сохранить link_id |
| 400 |
Bad Request |
Некорректные параметры запроса |
Проверить формат данных |
| 401 |
Unauthorized |
Отсутствует или невалидный токен |
Обновить токен авторизации |
| 409 |
Conflict |
Связь уже существует |
Проверить существующие связи |
| 429 |
Too Many Requests |
Превышен rate limit (10 req/min) |
Повторить через указанное в Retry-After время |
| 500 |
Internal Server Error |
Внутренняя ошибка сервиса |
Повторить запрос с экспоненциальной задержкой |
Алгоритм связывания
Псевдокод основного алгоритма
function process_profile_link(profile_a_id, profile_b_url):
# 1. Нормализация URL
profile_b_id = normalize_social_url(profile_b_url)
# 2. Проверка существования профилей в индексе
if not exists_in_index(profile_b_id):
schedule_crawl(profile_b_id)
return PENDING_CRAWL
# 3. Проверка взаимности связи
mutual = check_mutual_link(profile_b_id, profile_a_id)
# 4. Проверка OAuth-подтверждения (если применимо)
oauth_confirmed = check_oauth_link(profile_a_id, profile_b_id)
# 5. Определение типа связи и уровня доверия
if oauth_confirmed:
link_type = OAUTH_CONFIRMED
confidence = 1.0
elif mutual:
link_type = MUTUAL
confidence = 0.9
else:
return REJECTED_NO_MUTUAL
# 6. Получение существующих кластеров для обоих профилей
cluster_a = get_cluster(profile_a_id)
cluster_b = get_cluster(profile_b_id)
# 7. Объединение кластеров
if cluster_a and cluster_b:
if cluster_a.id == cluster_b.id:
return ALREADY_LINKED
merged_cluster = merge_clusters(cluster_a, cluster_b)
elif cluster_a:
merged_cluster = add_to_cluster(cluster_a, profile_b_id)
elif cluster_b:
merged_cluster = add_to_cluster(cluster_b, profile_a_id)
else:
merged_cluster = create_cluster([profile_a_id, profile_b_id])
# 8. Валидация размера кластера
if merged_cluster.size > MAX_CLUSTER_SIZE:
log_warning("Cluster size exceeded", cluster_id=merged_cluster.id)
trigger_manual_review(merged_cluster.id)
return REQUIRES_MANUAL_REVIEW
# 9. Публикация события в Kafka
publish_event("cluster.updated", {
"cluster_id": merged_cluster.id,
"profile_count": merged_cluster.size,
"timestamp": current_timestamp()
})
# 10. Обновление поискового индекса
schedule_index_update(merged_cluster.id)
return SUCCESS
Конфигурационные параметры
| Параметр |
Значение по умолчанию |
Переменная окружения |
Описание |
| MAX_CLUSTER_SIZE |
20 |
PGS_MAX_CLUSTER_SIZE |
Максимальное количество профилей в одном кластере |
| VALIDATION_TIMEOUT |
30s |
PGS_VALIDATION_TIMEOUT |
Таймаут для проверки взаимной ссылки |
| CRAWL_RATE_LIMIT |
100 req/s |
PGS_CRAWL_RATE_LIMIT |
Лимит запросов к социальным сетям в секунду |
| RETRY_ATTEMPTS |
3 |
PGS_RETRY_ATTEMPTS |
Количество попыток повтора при ошибке |
| RETRY_BACKOFF |
exponential (1s, 2s, 4s) |
PGS_RETRY_BACKOFF |
Стратегия задержки между повторными попытками |
Модель данных
Схема таблицы clusters
CREATE TABLE clusters (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
profile_count INTEGER NOT NULL DEFAULT 0,
status VARCHAR(20) NOT NULL DEFAULT 'active',
metadata JSONB,
CONSTRAINT chk_profile_count CHECK (profile_count >= 0 AND profile_count <= 20)
);
CREATE INDEX idx_clusters_updated_at ON clusters(updated_at);
CREATE INDEX idx_clusters_status ON clusters(status);
CREATE INDEX idx_clusters_profile_count ON clusters(profile_count) WHERE profile_count > 15;
Схема таблицы profiles
CREATE TABLE profiles (
id VARCHAR(255) PRIMARY KEY,
cluster_id UUID REFERENCES clusters(id) ON DELETE CASCADE,
platform VARCHAR(50) NOT NULL,
external_id VARCHAR(255) NOT NULL,
url TEXT NOT NULL,
display_name VARCHAR(255),
last_crawled_at TIMESTAMP,
is_public BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
CONSTRAINT profiles_id_format CHECK (id ~ '^[a-z]+:[0-9a-zA-Z_-]+$')
);
CREATE INDEX idx_profiles_cluster_id ON profiles(cluster_id);
CREATE INDEX idx_profiles_platform ON profiles(platform);
CREATE UNIQUE INDEX idx_profiles_platform_external ON profiles(platform, external_id);
CREATE INDEX idx_profiles_last_crawled ON profiles(last_crawled_at) WHERE is_public = TRUE;
Схема таблицы links
CREATE TABLE links (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
source_profile_id VARCHAR(255) REFERENCES profiles(id) ON DELETE CASCADE,
target_profile_id VARCHAR(255) REFERENCES profiles(id) ON DELETE CASCADE,
link_type VARCHAR(20) NOT NULL,
confidence DECIMAL(3,2) NOT NULL DEFAULT 0.9,
status VARCHAR(20) NOT NULL DEFAULT 'pending',
validated_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
CONSTRAINT chk_link_type CHECK (link_type IN ('manual', 'mutual', 'oauth')),
CONSTRAINT chk_confidence CHECK (confidence >= 0.0 AND confidence <= 1.0),
CONSTRAINT chk_status CHECK (status IN ('pending', 'validated', 'rejected'))
);
CREATE INDEX idx_links_source ON links(source_profile_id);
CREATE INDEX idx_links_target ON links(target_profile_id);
CREATE INDEX idx_links_status ON links(status);
CREATE UNIQUE INDEX idx_links_unique ON links(source_profile_id, target_profile_id);
Мониторинг и метрики
Ключевые метрики (SLI)
| Метрика |
Тип |
Целевое значение (SLO) |
Источник данных |
pgs_api_availability |
Gauge |
> 99.9% |
Prometheus |
pgs_api_latency_p95 |
Histogram |
< 500ms |
Prometheus |
pgs_validation_success_rate |
Counter |
> 95% |
Prometheus |
pgs_cluster_size_exceeded |
Counter |
< 10/day |
Prometheus |
pgs_worker_queue_size |
Gauge |
< 1000 |
Celery metrics |
Настроенные алерты
| Алерт |
Условие срабатывания |
Severity |
Действие oncall |
| PGS API Down |
pgs_api_availability < 99% |
Critical |
Page oncall-инженера, проверить логи и статус подов |
| High Latency |
pgs_api_latency_p95 > 1s |
Warning |
Проверить нагрузку на PostgreSQL и Redis |
| Queue Backlog |
pgs_worker_queue_size > 5000 |
Warning |
Увеличить количество Celery workers |
| Validation Failures |
pgs_validation_success_rate < 90% |
Warning |
Проверить доступность Social API Gateway |
| Suspicious Clusters |
pgs_cluster_size_exceeded > 50/day |
Warning |
Проверить логи на спам-активность, создать тикет для ручной проверки |
Дашборды мониторинга
| Система |
Дашборд |
Назначение |
| Grafana |
PGS Overview |
Общие метрики сервиса, доступность, latency |
| Grafana |
PGS API Metrics |
Детальные метрики API: эндпоинты, коды ответов, throughput |
| Sentry |
PGS Errors |
Трекинг ошибок и exceptions в приложении |
| Kibana |
PGS Logs |
Централизованные логи всех компонентов |
Runbook: Устранение инцидентов
Инцидент 1: API недоступен (HTTP 503)
Симптомы
- Все запросы к
/api/v1/* возвращают 503 Service Unavailable
- Алерт: PGS API Down (Critical)
- Grafana дашборд показывает
pgs_api_availability = 0%
Диагностика
# 1. Проверить статус подов Kubernetes
kubectl get pods -n pgs -l app=pgs-api
# 2. Проверить логи последних ошибок
kubectl logs -n pgs -l app=pgs-api --tail=100 --timestamps
# 3. Проверить доступность PostgreSQL
psql -h pgs-db.yandex.net -U pgs_user -d pgs_prod -c "SELECT 1;"
# 4. Проверить доступность Redis
redis-cli -h pgs-redis.yandex.net PING
# 5. Проверить Kafka consumer lag
kafka-consumer-groups --bootstrap-server kafka.yandex.net:9092 \
--group pgs-workers --describe
Решение
| Причина |
Решение |
Команда |
| Поды в статусе CrashLoopBackOff |
Перезапустить deployment |
kubectl rollout restart deployment/pgs-api -n pgs |
| PostgreSQL недоступна |
Эскалировать в DBA, включить read-only режим из Redis |
kubectl set env deployment/pgs-api PGS_READ_ONLY_MODE=true -n pgs |
| Kafka недоступна |
Временно отключить публикацию событий |
kubectl set env deployment/pgs-api PGS_KAFKA_ENABLED=false -n pgs |
| OOM (Out of Memory) |
Увеличить лимиты памяти |
kubectl set resources deployment/pgs-api --limits=memory=2Gi -n pgs |
Инцидент 2: Высокая задержка обработки запросов
Симптомы
pgs_api_latency_p95 > 2s
- Алерт: High Latency (Warning)
- Пользователи сообщают о медленном добавлении профилей
Диагностика
# 1. Проверить размер очереди Celery
celery -A pgs.worker inspect active_queues
# 2. Найти медленные запросы в PostgreSQL
SELECT query, mean_exec_time, calls
FROM pg_stat_statements
WHERE query LIKE '%profiles%'
ORDER BY mean_exec_time DESC
LIMIT 10;
# 3. Проверить hit rate кэша Redis
redis-cli INFO stats | grep keyspace
# 4. Проверить CPU и memory usage
kubectl top pods -n pgs
Решение
- Увеличить количество Celery workers:
kubectl scale deployment/pgs-worker --replicas=10 -n pgs
- Проверить и обновить индексы БД:
REINDEX TABLE profiles; ANALYZE profiles;
- Увеличить TTL кэша для часто запрашиваемых профилей:
kubectl set env deployment/pgs-api PGS_CACHE_TTL=3600 -n pgs
- Если проблема в PostgreSQL:
Проверить slow query log, добавить недостающие индексы, проконсультироваться с DBA
Инцидент 3: Кластер превысил максимальный размер
Симптомы
pgs_cluster_size_exceeded > 50/day
- Алерт: Suspicious Cluster Detected (Warning)
- В логах появляются записи:
Cluster size exceeded for cluster_id={uuid}
Диагностика
# 1. Найти подозрительные кластеры
SELECT id, profile_count, created_at, updated_at
FROM clusters
WHERE profile_count > 20
ORDER BY profile_count DESC
LIMIT 10;
# 2. Проверить профили в кластере
SELECT p.id, p.platform, p.display_name, p.url
FROM profiles p
WHERE cluster_id = '{cluster_id}'
ORDER BY p.created_at;
# 3. Проверить связи в кластере
SELECT l.id, l.source_profile_id, l.target_profile_id, l.link_type, l.confidence
FROM links l
JOIN profiles p ON (l.source_profile_id = p.id OR l.target_profile_id = p.id)
WHERE p.cluster_id = '{cluster_id}';
Решение
- Анализ профилей: Определить, является ли это ботом, спамером или легитимным пользователем (например, публичной личностью с множеством профилей)
- Если спам/бот:
UPDATE clusters SET status = 'suspicious' WHERE id = '{cluster_id}';
- Исключить из отображения в поиске:
Добавить кластер в blacklist для SERP Service
- Создать тикет для ручной проверки:
В системе тикетов указать cluster_id, количество профилей, подозрительные паттерны
- Если легитимный случай:
Увеличить MAX_CLUSTER_SIZE для конкретного пользователя через metadata кластера
История изменений
| Версия |
Дата |
Автор |
Изменения |
| 2.0.0 |
2025-11-03 |
Иванов И.И. |
Полная переработка документации. Добавлены runbook, API спецификация, мониторинг. Интеграция английской локализации. |
| 1.5.0 |
2024-06-15 |
Петров П.П. |
Добавлена поддержка OAuth-интеграций с X (Twitter) и LinkedIn. Обновлён механизм валидации подтверждённых ссылок. |
| 1.4.0 |
2023-11-20 |
Сидоров С.С. |
Оптимизация алгоритма валидации. Уменьшено среднее время обработки с 72 до 48 часов за счёт параллельной проверки ссылок. |
| 1.3.0 |
2023-03-10 |
Иванов И.И. |
Миграция на PostgreSQL 14. Добавлены составные индексы для ускорения запросов поиска профилей по кластерам. |
| 1.2.0 |
2022-08-05 |
Петров П.П. |
Добавлена поддержка Одноклассников через механизм Яндекс ID. Реализован fallback для сетей без взаимных ссылок. |
| 1.1.0 |
2021-12-01 |
Сидоров С.С. |
Реализован механизм проверки взаимных ссылок для ВКонтакте. Добавлена таблица links в схему БД. |
| 1.0.0 |
2021-05-15 |
Иванов И.И. |
Первый production-релиз Profile Grouping Service. Базовая функциональность связывания через Яндекс ID. |
Связанные документы
Technical overview
Service purpose
Profile Grouping Service (PGS) is a microservice responsible for discovering, validating, and aggregating links between user profiles across various social networks to form a consolidated representation in Yandex's search index.
Owners and contacts
| Role |
Team / Person |
Contact |
| Service Owner |
Search Services Team |
search-team@yandex-team.ru |
| Tech Lead |
Ivanov I.I. |
ivanov@yandex-team.ru |
| On-call Engineer |
Rotation schedule |
Slack: #search-oncall |
Responsibilities
- Processing events from Yandex ID when adding/removing social connections
- Parsing structured data from social network profiles
- Validating mutual links between profiles
- Integrating with social network OAuth APIs to verify confirmed links
- Forming and updating profile clusters
- Publishing cluster change events to the data bus
Out of scope
- Social network content indexing (responsibility: Indexing Pipeline)
- Yandex ID account storage and management (responsibility: Passport Service)
- Search results display (responsibility: SERP Service)
System architecture
Components
| Component |
Technology |
Purpose |
pgs-api |
Python 3.11, FastAPI |
REST API for profile link management |
pgs-worker |
Python 3.11, Celery |
Asynchronous processing of linking and validation tasks |
pgs-crawler |
Go 1.21 |
Social network profile parsing and metadata extraction |
pgs-validator |
Python 3.11 |
Mutual link validation and confirmation verification |
External system dependencies
| System |
Purpose |
Criticality |
| Passport Service |
Authentication, profile addition events |
Critical |
| Indexing Pipeline |
Profile data from search index |
Critical |
| Social API Gateway |
Proxying requests to social network APIs |
High |
| PostgreSQL |
Storage for clusters, profiles, and links |
Critical |
| Redis |
Caching, rate limiting |
Medium |
| Kafka |
Event bus for inter-service communication |
High |
Deployment topology
[Passport Service]
|
| (Kafka event: profile.linked)
v
[pgs-worker] --> [pgs-validator] --> [pgs-crawler]
| |
v v
[PostgreSQL] [Social API Gateway]
|
v
[Kafka event: cluster.updated] --> [Indexing Pipeline]
API and integrations
REST API endpoints
| Method |
Path |
Description |
Authentication |
| GET |
/api/v1/clusters/:user_id |
Retrieve user profile cluster |
OAuth token |
| POST |
/api/v1/links |
Add link between profiles |
OAuth token |
| DELETE |
/api/v1/links/:link_id |
Remove link by identifier |
OAuth token |
| POST |
/api/v1/clusters/reindex |
Force cluster reindexing |
Service token |
Request example
POST /api/v1/links HTTP/1.1
Host: pgs.yandex.net
Authorization: OAuth ya29.a0AfH6SMBx...
Content-Type: application/json
{
"source_profile_id": "vk:12345678",
"target_profile_url": "https://www.facebook.com/john.doe",
"link_type": "manual"
}
Response example (success)
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/links/lnk_9a8b7c6d5e4f
{
"link_id": "lnk_9a8b7c6d5e4f",
"status": "pending_validation",
"created_at": "2025-11-03T14:23:45Z",
"estimated_processing_time": "48h"
}
HTTP response codes
| Code |
Meaning |
Description |
Client Action |
| 200 |
OK |
Request completed successfully |
Process response |
| 201 |
Created |
Link created |
Store link_id |
| 400 |
Bad Request |
Invalid request parameters |
Check data format |
| 401 |
Unauthorized |
Missing or invalid token |
Refresh authorization token |
| 409 |
Conflict |
Link already exists |
Check existing links |
| 429 |
Too Many Requests |
Rate limit exceeded (10 req/min) |
Retry after time specified in Retry-After header |
| 500 |
Internal Server Error |
Internal service error |
Retry request with exponential backoff |
Linking algorithm
Main algorithm pseudocode
function process_profile_link(profile_a_id, profile_b_url):
# 1. URL normalization
profile_b_id = normalize_social_url(profile_b_url)
# 2. Check profile existence in index
if not exists_in_index(profile_b_id):
schedule_crawl(profile_b_id)
return PENDING_CRAWL
# 3. Check link reciprocity
mutual = check_mutual_link(profile_b_id, profile_a_id)
# 4. Check OAuth confirmation (if applicable)
oauth_confirmed = check_oauth_link(profile_a_id, profile_b_id)
# 5. Determine link type and confidence level
if oauth_confirmed:
link_type = OAUTH_CONFIRMED
confidence = 1.0
elif mutual:
link_type = MUTUAL
confidence = 0.9
else:
return REJECTED_NO_MUTUAL
# 6. Retrieve existing clusters for both profiles
cluster_a = get_cluster(profile_a_id)
cluster_b = get_cluster(profile_b_id)
# 7. Merge clusters
if cluster_a and cluster_b:
if cluster_a.id == cluster_b.id:
return ALREADY_LINKED
merged_cluster = merge_clusters(cluster_a, cluster_b)
elif cluster_a:
merged_cluster = add_to_cluster(cluster_a, profile_b_id)
elif cluster_b:
merged_cluster = add_to_cluster(cluster_b, profile_a_id)
else:
merged_cluster = create_cluster([profile_a_id, profile_b_id])
# 8. Validate cluster size
if merged_cluster.size > MAX_CLUSTER_SIZE:
log_warning("Cluster size exceeded", cluster_id=merged_cluster.id)
trigger_manual_review(merged_cluster.id)
return REQUIRES_MANUAL_REVIEW
# 9. Publish event to Kafka
publish_event("cluster.updated", {
"cluster_id": merged_cluster.id,
"profile_count": merged_cluster.size,
"timestamp": current_timestamp()
})
# 10. Schedule search index update
schedule_index_update(merged_cluster.id)
return SUCCESS
Configuration parameters
| Parameter |
Default Value |
Environment Variable |
Description |
| MAX_CLUSTER_SIZE |
20 |
PGS_MAX_CLUSTER_SIZE |
Maximum number of profiles in one cluster |
| VALIDATION_TIMEOUT |
30s |
PGS_VALIDATION_TIMEOUT |
Timeout for mutual link verification |
| CRAWL_RATE_LIMIT |
100 req/s |
PGS_CRAWL_RATE_LIMIT |
Request limit to social networks per second |
| RETRY_ATTEMPTS |
3 |
PGS_RETRY_ATTEMPTS |
Number of retry attempts on error |
| RETRY_BACKOFF |
exponential (1s, 2s, 4s) |
PGS_RETRY_BACKOFF |
Delay strategy between retry attempts |
Data model
Clusters table schema
CREATE TABLE clusters (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
profile_count INTEGER NOT NULL DEFAULT 0,
status VARCHAR(20) NOT NULL DEFAULT 'active',
metadata JSONB,
CONSTRAINT chk_profile_count CHECK (profile_count >= 0 AND profile_count <= 20)
);
CREATE INDEX idx_clusters_updated_at ON clusters(updated_at);
CREATE INDEX idx_clusters_status ON clusters(status);
CREATE INDEX idx_clusters_profile_count ON clusters(profile_count) WHERE profile_count > 15;
Profiles table schema
CREATE TABLE profiles (
id VARCHAR(255) PRIMARY KEY,
cluster_id UUID REFERENCES clusters(id) ON DELETE CASCADE,
platform VARCHAR(50) NOT NULL,
external_id VARCHAR(255) NOT NULL,
url TEXT NOT NULL,
display_name VARCHAR(255),
last_crawled_at TIMESTAMP,
is_public BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
CONSTRAINT profiles_id_format CHECK (id ~ '^[a-z]+:[0-9a-zA-Z_-]+$')
);
CREATE INDEX idx_profiles_cluster_id ON profiles(cluster_id);
CREATE INDEX idx_profiles_platform ON profiles(platform);
CREATE UNIQUE INDEX idx_profiles_platform_external ON profiles(platform, external_id);
CREATE INDEX idx_profiles_last_crawled ON profiles(last_crawled_at) WHERE is_public = TRUE;
Links table schema
CREATE TABLE links (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
source_profile_id VARCHAR(255) REFERENCES profiles(id) ON DELETE CASCADE,
target_profile_id VARCHAR(255) REFERENCES profiles(id) ON DELETE CASCADE,
link_type VARCHAR(20) NOT NULL,
confidence DECIMAL(3,2) NOT NULL DEFAULT 0.9,
status VARCHAR(20) NOT NULL DEFAULT 'pending',
validated_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
CONSTRAINT chk_link_type CHECK (link_type IN ('manual', 'mutual', 'oauth')),
CONSTRAINT chk_confidence CHECK (confidence >= 0.0 AND confidence <= 1.0),
CONSTRAINT chk_status CHECK (status IN ('pending', 'validated', 'rejected'))
);
CREATE INDEX idx_links_source ON links(source_profile_id);
CREATE INDEX idx_links_target ON links(target_profile_id);
CREATE INDEX idx_links_status ON links(status);
CREATE UNIQUE INDEX idx_links_unique ON links(source_profile_id, target_profile_id);
Monitoring and metrics
Key metrics (SLI)
| Metric |
Type |
Target (SLO) |
Data Source |
pgs_api_availability |
Gauge |
> 99.9% |
Prometheus |
pgs_api_latency_p95 |
Histogram |
< 500ms |
Prometheus |
pgs_validation_success_rate |
Counter |
> 95% |
Prometheus |
pgs_cluster_size_exceeded |
Counter |
< 10/day |
Prometheus |
pgs_worker_queue_size |
Gauge |
< 1000 |
Celery metrics |
Configured alerts
| Alert |
Trigger Condition |
Severity |
Oncall Action |
| PGS API Down |
pgs_api_availability < 99% |
Critical |
Page oncall engineer, check logs and pod status |
| High Latency |
pgs_api_latency_p95 > 1s |
Warning |
Check PostgreSQL and Redis load |
| Queue Backlog |
pgs_worker_queue_size > 5000 |
Warning |
Increase number of Celery workers |
| Validation Failures |
pgs_validation_success_rate < 90% |
Warning |
Check Social API Gateway availability |
| Suspicious Clusters |
pgs_cluster_size_exceeded > 50/day |
Warning |
Check logs for spam activity, create ticket for manual review |
Monitoring dashboards
| System |
Dashboard |
Purpose |
| Grafana |
PGS Overview |
Overall service metrics, availability, latency |
| Grafana |
PGS API Metrics |
Detailed API metrics: endpoints, response codes, throughput |
| Sentry |
PGS Errors |
Application error and exception tracking |
| Kibana |
PGS Logs |
Centralized logs from all components |
Runbook: Incident response
Incident 1: API unavailable (HTTP 503)
Symptoms
- All requests to
/api/v1/* return 503 Service Unavailable
- Alert: PGS API Down (Critical)
- Grafana dashboard shows
pgs_api_availability = 0%
Diagnostics
# 1. Check Kubernetes pod status
kubectl get pods -n pgs -l app=pgs-api
# 2. Check recent error logs
kubectl logs -n pgs -l app=pgs-api --tail=100 --timestamps
# 3. Check PostgreSQL availability
psql -h pgs-db.yandex.net -U pgs_user -d pgs_prod -c "SELECT 1;"
# 4. Check Redis availability
redis-cli -h pgs-redis.yandex.net PING
# 5. Check Kafka consumer lag
kafka-consumer-groups --bootstrap-server kafka.yandex.net:9092 \
--group pgs-workers --describe
Resolution
| Cause |
Solution |
Command |
| Pods in CrashLoopBackOff |
Restart deployment |
kubectl rollout restart deployment/pgs-api -n pgs |
| PostgreSQL unavailable |
Escalate to DBA, enable read-only mode from Redis |
kubectl set env deployment/pgs-api PGS_READ_ONLY_MODE=true -n pgs |
| Kafka unavailable |
Temporarily disable event publishing |
kubectl set env deployment/pgs-api PGS_KAFKA_ENABLED=false -n pgs |
| OOM (Out of Memory) |
Increase memory limits |
kubectl set resources deployment/pgs-api --limits=memory=2Gi -n pgs |
Incident 2: High request processing latency
Symptoms
pgs_api_latency_p95 > 2s
- Alert: High Latency (Warning)
- Users report slow profile addition
Diagnostics
# 1. Check Celery queue size
celery -A pgs.worker inspect active_queues
# 2. Find slow queries in PostgreSQL
SELECT query, mean_exec_time, calls
FROM pg_stat_statements
WHERE query LIKE '%profiles%'
ORDER BY mean_exec_time DESC
LIMIT 10;
# 3. Check Redis cache hit rate
redis-cli INFO stats | grep keyspace
# 4. Check CPU and memory usage
kubectl top pods -n pgs
Resolution
- Increase Celery workers:
kubectl scale deployment/pgs-worker --replicas=10 -n pgs
- Check and update database indexes:
REINDEX TABLE profiles; ANALYZE profiles;
- Increase cache TTL for frequently requested profiles:
kubectl set env deployment/pgs-api PGS_CACHE_TTL=3600 -n pgs
- If issue in PostgreSQL:
Review slow query log, add missing indexes, consult with DBA
Incident 3: Cluster exceeded maximum size
Symptoms
pgs_cluster_size_exceeded > 50/day
- Alert: Suspicious Cluster Detected (Warning)
- Logs show:
Cluster size exceeded for cluster_id={uuid}
Diagnostics
# 1. Find suspicious clusters
SELECT id, profile_count, created_at, updated_at
FROM clusters
WHERE profile_count > 20
ORDER BY profile_count DESC
LIMIT 10;
# 2. Check profiles in cluster
SELECT p.id, p.platform, p.display_name, p.url
FROM profiles p
WHERE cluster_id = '{cluster_id}'
ORDER BY p.created_at;
# 3. Check links in cluster
SELECT l.id, l.source_profile_id, l.target_profile_id, l.link_type, l.confidence
FROM links l
JOIN profiles p ON (l.source_profile_id = p.id OR l.target_profile_id = p.id)
WHERE p.cluster_id = '{cluster_id}';
Resolution
- Profile analysis: Determine if this is a bot, spammer, or legitimate user (e.g., public figure with multiple profiles)
- If spam/bot:
UPDATE clusters SET status = 'suspicious' WHERE id = '{cluster_id}';
- Exclude from search display:
Add cluster to blacklist for SERP Service
- Create ticket for manual review:
In ticketing system specify cluster_id, profile count, suspicious patterns
- If legitimate case:
Increase MAX_CLUSTER_SIZE for specific user via cluster metadata
Changelog
| Version |
Date |
Author |
Changes |
| 2.0.0 |
2025-11-03 |
Ivanov I.I. |
Complete documentation overhaul. Added runbook, API specification, monitoring. Integrated English localization. |
| 1.5.0 |
2024-06-15 |
Petrov P.P. |
Added OAuth integration support for X (Twitter) and LinkedIn. Updated confirmed link validation mechanism. |
| 1.4.0 |
2023-11-20 |
Sidorov S.S. |
Validation algorithm optimization. Reduced average processing time from 72 to 48 hours via parallel link verification. |
| 1.3.0 |
2023-03-10 |
Ivanov I.I. |
Migration to PostgreSQL 14. Added composite indexes for accelerating cluster profile search queries. |
| 1.2.0 |
2022-08-05 |
Petrov P.P. |
Added Odnoklassniki support via Yandex ID mechanism. Implemented fallback for networks without mutual links. |
| 1.1.0 |
2021-12-01 |
Sidorov S.S. |
Implemented mutual link verification mechanism for VKontakte. Added links table to DB schema. |
| 1.0.0 |
2021-05-15 |
Ivanov I.I. |
First production release of Profile Grouping Service. Basic linking functionality via Yandex ID. |
Related documents