Регламент удаления данных: как удалять, чтобы копии не остались в бэкапах
Пользователь нажал «удалить аккаунт», вы стёрли его строку из базы — и формально обещание выполнено. Но данные из этой строки всё ещё живут в семи дневных, четырёх недельных и двенадцати месячных бэкапах, и последний снимок с этой записью протухнет только через год. Если это разовая история — почти неважно. Если это регламент, на который смотрит юрист или сам пользователь, задающий прямой вопрос «а точно всё удалено?» — здесь и начинается разговор, который редко проговаривают заранее. Разберём, как построить регламент удаления, который не врёт о сроках и технически выполним.
Содержание
- Почему «удалено» и «удалено везде» — разные обещания
- Матрица: что действительно требует гарантированного удаления
- Подход первый: удаление привязано к сроку хранения бэкапов
- Подход второй: гарантированное удаление для критичных случаев
- Где эта задача усложняется: неизменяемые бэкапы
- Как это документировать и что говорить пользователю
Почему «удалено» и «удалено везде» — разные обещания
Удаление данных из продовой базы — операция, которая занимает миллисекунды. Удаление данных из всех мест, где они когда-либо побывали, — совсем другая задача, и её масштаб обычно недооценивают на старте проекта, пока не приходит первый запрос на удаление от реального человека.
Данные одного пользователя к моменту удаления обычно живут не в одном месте:
- продовая база (то, что удаляется мгновенно и это единственное место, где действительно так);
- реплики для чтения — обновятся с задержкой в секунды, но обновятся;
- кеш (Redis, CDN) — TTL истечёт сам, если он вообще выставлен;
- очереди и логи приложения — могут содержать payload с персональными данными;
- поисковый индекс (Elasticsearch, Meilisearch) — требует отдельного запроса на удаление документа;
- аналитика и BI-хранилища, куда данные выгружались ETL-процессом;
- бэкапы — вот здесь и начинается настоящая проблема.
Бэкап по своей природе — это снимок состояния системы на конкретный момент времени. Как только он снят, он неизменен: это его единственная гарантия полезности. Вы не можете «зайти» в бэкап недельной давности и вычеркнуть оттуда одну строку так же, как в продовой базе — по крайней мере не без того, чтобы не сломать саму идею бэкапа как проверяемого, целостного слепка. Значит, данные конкретного пользователя физически присутствуют в каждом бэкапе, который был снят до момента удаления, и будут присутствовать там до тех пор, пока этот бэкап не будет удалён по ротации.
Если у вас хранится 90 дней бэкапов — значит, после удаления записи из продакшена копия этой записи технически ещё до 90 дней доступна тому, кто получит доступ к архиву бэкапов. Это не брак в процессе, а прямое следствие того, зачем бэкапы вообще существуют — восстановить состояние системы, включая то, что было до удаления.
Матрица: что действительно требует гарантированного удаления
Не всякое удаление данных требует героических усилий по вычищению бэкапов. Прежде чем городить инфраструктуру для «удаления из бэкапов», стоит честно разделить данные на категории — это экономит и деньги, и нервы.
| Категория данных | Типичный подход | Нужна ли гарантия удаления из бэкапов |
|---|---|---|
| Обычный контент пользователя (посты, файлы, настройки) | Ожидание истечения ретеншена бэкапов | Как правило, нет |
| Учётные данные, платёжные токены | Отзыв на стороне провайдера сразу + ожидание ретеншена | Отзыв — да, полное стирание из бэкапов — обычно нет |
| Данные под явным запросом на удаление (право на удаление) | Зависит от юрисдикции и договора с пользователем | Иногда да — определяет юрист, не инженер |
| Секреты, ключи API, пароли в открытом виде | Ротация секрета делает старую копию бесполезной | Технически нет, потому что компрометация снимается ротацией, а не удалением байтов |
| Медицинские, биометрические и другие данные с повышенными требованиями | Индивидуальная политика, часто с юридическим сопровождением | Да, но это решает не техническая команда в одиночку |
Ключевая мысль этой таблицы: для большинства данных «удалить и подождать, пока состарятся бэкапы» — это не отговорка, а рабочая, юридически объяснимая практика, если она заранее прописана в политике и об этом честно сказано пользователю. А для меньшинства случаев — данных с реальным риском при утечке — нужен отдельный механизм, и его стоимость должна быть осознанной, а не «сделаем на коленке, когда попросят».
Разделение данных на эти категории — не разовое упражнение, а часть общей политики обработки данных: она должна явно фиксировать, какие поля считаются чувствительными и какой режим удаления к ним применяется.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверПодход первый: удаление привязано к сроку хранения бэкапов
Самый честный и самый дешёвый в реализации подход — сделать срок хранения бэкапов частью формулы удаления, а не игнорировать его. Формула простая:
Реальный момент полного удаления = момент удаления из продакшена + максимальный срок хранения бэкапа, в котором эти данные ещё встречаются
Если у вас ротация бэкапов 30 дней — значит, максимум через 30 дней после удаления из продакшена данных не останется нигде, включая архив. Если 12 месяцев — значит, 12 месяцев. Это не костыль, это ровно то, что нужно прописать в регламенте:
# Пример фиксации в политике (внутренний документ, не для публикации как есть)
retention:
daily_backups: 7d
weekly_backups: 5w
monthly_backups: 13m # чуть больше года ради сравнения год-к-году
deletion_policy:
production: immediate # удаление из БД — сразу по запросу
backups: passive_expiry # ждём истечения ротации, отдельно не трогаем
max_full_erasure_window: 13m # верхняя граница = самый долгий бэкап
Дальше остаётся синхронизировать это с тем, что вы говорите пользователю. Не «ваши данные удалены немедленно», а формулировка вроде «данные удаляются из активных систем сразу, полное удаление из резервных копий завершается в течение [срока], соответствующего циклу ротации бэкапов» — с реальным числом из вашей ротации бэкапов. Это честно, проверяемо и не создаёт обещаний, которые инфраструктура не может выполнить.
Практический плюс этого подхода — он не требует отдельной инженерной работы сверх той, что вы и так делаете: ротация бэкапов и так должна быть настроена и предсказуема. Минус — он не годится, если бизнес или закон требуют гарантированного удаления быстрее, чем истекает самый долгий бэкап. Тогда нужен подход номер два.
Подход второй: гарантированное удаление для критичных случаев
Если для части данных пассивное ожидание ротации не годится — например, договор с корпоративным клиентом прямо требует подтверждённого удаления в течение недель, а не месяцев — нужен отдельный механизм, и он почти всегда сводится к одной из трёх техник.
Криптографическое стирание (crypto-shredding). Данные, которые потенциально попадут под удаление, шифруются собственным ключом — на уровне записи, тенанта или пользователя, отдельно от общего шифрования диска. Чтобы «удалить» данные из всех бэкапов сразу, достаточно уничтожить ключ: без него зашифрованный блок в архиве становится нечитаемым мусором, даже если физически байты никуда не делись. Это единственный способ добиться результата, близкого к «удалено везде и сразу», не трогая сами файлы бэкапа.
# Пример на уровне файла с помощью age — свой ключ на пользователя/тенанта
age -e -r age1qyq...user42pubkey... -o user_42_payload.enc user_42_payload.json
# при запросе на удаление — просто уничтожаем приватный ключ пользователя 42
shred -u user_42_privkey.txt
Оговорка сразу: это требует архитектурного решения, принятого заранее — до того, как данные попали в первый бэкап. Пристроить crypto-shredding к системе, где всё уже год льётся в общий bcrypt-зашифрованный дамп postgres, нельзя — придётся перепроектировать хранение для конкретных чувствительных полей.
Точечная зачистка бэкапов инструментом. Некоторые инструменты резервного копирования (restic, borgbackup) позволяют удалить конкретные снапшоты и прогнать prune, но это удаляет снапшот целиком, а не одну запись внутри него — и после prune предыдущие точки восстановления теряются полностью, не только спорная строка.
# restic: посмотреть, какие снапшоты вообще есть
restic snapshots
# удалить конкретные снапшоты и почистить неиспользуемые данные хранилища
restic forget --keep-tag legal-hold --prune
Годится, если политика допускает удалить «весь срез на такую-то дату», а не хирургически вычистить одну строку — и если вы готовы потерять возможность откатиться к этой точке целиком.
Пересборка бэкапа без спорных данных. Технически возможно: восстановить снапшот во временное окружение, удалить нужные записи, пересобрать бэкап и заменить старый. Это дорого по ресурсам, ломает неизменяемость архива (что само по себе противоречит цели бэкапа — быть проверяемым и целостным) и оправдано только для единичных случаев с высокой ценой ошибки, не как массовый процесс на каждый запрос пользователя.
Где эта задача усложняется: неизменяемые бэкапы
Если у вас настроены неизменяемые бэкапы — снапшоты с object lock или WORM-хранилищем, которые нельзя изменить или удалить раньше срока даже с правами администратора — это отличная защита от шифровальщика и инсайдера, но она прямо конфликтует с идеей «удалить конкретную запись из архива по требованию».
Это не повод отказываться от неизменяемости — она защищает от куда более вероятного и разрушительного сценария (компрометация учётки с правами на бэкапы, программа-вымогатель). Но при проектировании политики удаления это нужно учитывать явно: если часть бэкапов зафиксирована в режиме object lock на 90 дней, то гарантированное удаление раньше этого срока для данных внутри них физически невозможно, пока не истечёт lock — и никакой скрипт это не обойдёт, в этом весь смысл object lock.
Практический вывод — планировать заранее: если вы знаете, что бизнесу понадобится гарантированное удаление по запросу, либо не включайте immutable-режим на бэкапы с чувствительными данными, либо сразу закладывайте crypto-shredding как основной механизм, а не полагайтесь на то, что сможете «просто зайти и удалить снапшот».
Как это документировать и что говорить пользователю
Регламент удаления данных бесполезен, если он живёт только в голове инженера, который его настраивал. Минимальный набор, который должен быть зафиксирован письменно:
- Срок полного исчезновения данных по каждой категории — с привязкой к реальной ротации бэкапов, а не к абстрактному «в разумный срок».
- Кто отвечает за обработку запроса на удаление — конкретная роль, а не «кто увидит тикет».
- Что происходит немедленно, а что — по мере истечения бэкапов: разделяйте эти два события явно в тексте, который видит пользователь.
- Список систем, где данные пользователя вообще могут оказаться — включая аналитику, логи, кеши, сторонние сервисы (email-рассылки, платёжные шлюзы), не только основную БД.
- Формулировка для пользователя, которая не обещает того, чего система не может выполнить технически.
Пример честной формулировки, которую можно адаптировать под свой сервис:
При удалении аккаунта ваши данные немедленно удаляются
из активных систем и становятся недоступны для дальнейшей
обработки. Резервные копии, снятые до момента удаления,
могут содержать эти данные до истечения срока их хранения
(до N дней/месяцев согласно графику ротации бэкапов) и
используются исключительно для аварийного восстановления
системы, не для повторной обработки ваших данных.
Здесь нет юридической консультации — только техническое описание того, что реально происходит с данными. Формулировки о правовых основаниях, сроках по конкретному законодательству и о том, распространяется ли на ваш сервис право на удаление в том или ином виде — это к юристу, специализирующемуся на защите данных в вашей юрисдикции, а не к DevOps-регламенту. Инженерная часть отвечает за то, чтобы обещание, которое даёт юрист или служба поддержки, было технически выполнимым — а не наоборот.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли вообще удалить данные из бэкапа мгновенно и без следа?
Технически — только через crypto-shredding, спроектированный заранее (уничтожение ключа шифрования делает данные нечитаемыми). Без такой архитектуры «мгновенное полное удаление из всех бэкапов» физически противоречит тому, как устроены надёжные системы резервного копирования — неизменяемость снимка и есть их главная гарантия целостности.
Что если пользователь настаивает на немедленном удалении из всех копий?
Объясните технически честно: активные системы очищаются сразу, бэкапы — по графику ротации, который вы можете назвать конкретным числом. Если для конкретного случая нужна гарантия быстрее — это отдельный процесс с ценой (crypto-shredding, зачистка снапшота целиком), и решение о его применении — организационное, не чисто инженерное.
Нужно ли сокращать срок хранения бэкапов, чтобы упростить удаление?
Это компромисс с устойчивостью: чем короче срок хранения, тем быстрее данные исчезают отовсюду, но тем меньше у вас глубины восстановления при инциденте, обнаруженном не сразу. Решение стоит принимать осознанно, а не как побочный эффект политики удаления.
Достаточно ли просто удалить запись из продовой базы и не думать про бэкапы?
Для большинства обычных данных — да, если это прописано в политике и озвучено пользователю честно. Проблема возникает не от самого факта наличия данных в бэкапах, а от того, что об этом никто не предупредил заранее.
Как быть с логами, где персональные данные оказались случайно?
Это отдельная и частая проблема — она разобрана в материале про то, что считается персональными данными: токены и ID пользователей в логах нередко подпадают под то же определение, что и данные в основной базе, и требуют той же дисциплины хранения.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →