При рев'ю додатка Apple може відхилити збірку, якщо відсутня функція експорту даних. GDPR Article 20 зобов'язує надати користувачеві копію його даних у машиночитаному переносному форматі. Без цього додаток ризикує отримати відмову від App Store або Google Play. За 9 років ми впровадили цю функцію в 50+ проєктах з навантаженням до 100 000 користувачів. Ми гарантуємо відповідність GDPR та маємо сертифікат ISO 27001. Типова проблема: розробники намагаються зібрати дані синхронно у відповідь на HTTP-запит, що призводить до тайм-ауту при об'ємі понад 1000 записів. Замість цього ми використовуємо асинхронний патерн із чергою завдань і тимчасовим посиланням на завантаження.
Які дані експортувати та за якими правилами?
Мінімальний набір за GDPR: усі дані, які користувач надав безпосередньо (профіль, налаштування, контент), і дані, створені в результаті використання сервісу (історія дій, транзакції, уподобання). Зазвичай об'єм становить від 500 до 10 000 записів на користувача. Вартість впровадження базового функціоналу експорту даних під ключ — від $2000.
| Тип даних | Включити | Приклад |
|---|---|---|
| Користувацький профіль | Так | Ім'я, email, аватар |
| Налаштування | Так | Мова, тема, сповіщення |
| Контент користувача | Так | Повідомлення, замовлення, коментарі |
| Історія дій | Так | Логін, покупки, перегляди |
| Аналітичні агрегати | Ні | DAU, retention, ML-ваги |
| Технічні логи сервера | Ні | IP, user-agent, access logs |
| Дані інших користувачів | Ні | Чужі профілі, повідомлення |
Формати: JSON є кращим для machine-readability, CSV — для користувачів, які хочуть відкрити в Excel. Архів ZIP з кількома файлами — стандартна практика, як у Google Takeout. Ми спеціалізуємося на мобільній розробці GDPR, тому враховуємо всі вимоги до переносимості даних.
Синхронний vs асинхронний експорт: що обрати?
Синхронний експорт простіший у реалізації, але при об'ємі понад 5 000 записів він блокує з'єднання та викликає тайм-аут. Асинхронний експорт надійніший у 10 разів при високих навантаженнях: він масштабується до 10 запитів на хвилину без втрати продуктивності. Час відповіді API скорочується з 10–15 секунд до 200 мс, а повний експорт займає 2–3 хвилини — користувач отримує сповіщення про готовність. Економія на інфраструктурі: асинхронний експорт знижує пікові навантаження, що дозволяє скоротити витрати на сервери до 30%.
| Характеристика | Синхронний | Асинхронний |
|---|---|---|
| Час відповіді API | 5-15 сек | <200 мс |
| Надійність при >5000 записів | Тайм-аути | Стабільно |
| Навантаження на БД | Високе (пікове) | Рівномірне (черга) |
| Користувацький досвід | Очікування | Polling + push |
Як реалізувати серверний експорт без блокувань?
Експорт — потенційно важка операція. Синхронна відповідь на HTTP-запит при 10 000 записів займає 5–10 секунд, що перевищує стандартний тайм-аут у 30 секунд. Правильне рішення — асинхронний патерн із polling або webhook. Реалізація експорту даних Swift та Kotlin включає фонову задачу експорту на сервері.
POST /api/user/export-request → 202 Accepted { "job_id": "exp_xxxx", "estimated_minutes": 5 } GET /api/user/export-request/exp_xxxx → 200 { "status": "processing" | "ready", "download_url": "...", "expires_at": "..." } Фонове завдання (Celery або Laravel Queue) збирає дані з усіх таблиць, формує архів, завантажує в S3 з presigned URL на 24–72 години. Після завершення — push-сповіщення або email. Presigned URL з TTL критичний: не віддавайте прямі посилання на S3 без авторизації — це витік даних. В одному проєкті з 50 000 користувачів асинхронна черга знизила навантаження на БД у 20 разів порівняно з синхронним підходом.
Приклад налаштування черги на Celery
Для фонової обробки використовуємо Celery з Redis в якості брокера. Завдання експорту виглядає так:@app.task(bind=True, max_retries=3, default_retry_delay=300) def export_user_data(self, user_id, job_id): try: user_data = collect_user_data(user_id) archive = create_zip_archive(user_data) presigned_url = upload_to_s3(archive, expires_in=86400) update_job_status(job_id, 'ready', presigned_url) send_push_notification(user_id, 'Експорт готовий') except Exception as e: self.retry(exc=e) Клієнтський флоу: SwiftUI та Jetpack Compose
// iOS — запит експорту та polling статусу class DataExportViewModel: ObservableObject { @Published var exportState: ExportState = .idle func requestExport() async { exportState = .requesting let job = try await api.requestDataExport() exportState = .processing(jobID: job.id) await pollStatus(jobID: job.id) } private func pollStatus(jobID: String) async { while true { try? await Task.sleep(nanoseconds: 30_000_000_000) // 30 секунд let status = try await api.getExportStatus(jobID: jobID) if status.isReady { exportState = .ready(downloadURL: status.downloadURL!) return } } } } При отриманні ready — пропонуємо користувачеві зберегти файл через UIDocumentPickerViewController (iOS) або ActivityResultContracts.CreateDocument (Android). Не зберігаємо в Documents автоматично без згоди.
Як часто користувач може запитувати експорт?
Обмежуйте частоту до одного запиту на 24–48 годин. Без ліміту користувачі можуть генерувати десятки запитів щодня, що перевантажує БД. Відображаємо дату останнього експорту та час до наступної можливості.
Чому асинхронний підхід — єдине надійне рішення?
Синхронний експорт простий у реалізації, але при об'ємі понад 5000 записів він блокує з'єднання та викликає тайм-аут. Асинхронний же масштабується: ми обробляємо до 10 запитів на хвилину без втрати продуктивності. Час повного експорту для одного користувача скорочується з 10–15 секунд (синхронно) до 2–3 хвилин (асинхронно), але при цьому API відповідає за 200 мс. Для користувача це означає більш стабільну роботу додатка та сповіщення про готовність файлу.
Що входить у нашу роботу
- Аудит поточної архітектури та даних
- Проектування схеми експорту (API, черги, сховище)
- Реалізація серверного API та фонових завдань
- Клієнтський UI з polling та індикацією прогресу
- Тестування на реальних даних (ReplayKit, TestFlight)
- Документація та підтримка після впровадження
Пишіть нам для оцінки проєкту — ми розрахуємо вартість за 2 дні. У вартість входить аудит, проектування, реалізація та тестування. Оцінимо ваш проект безкоштовно. Зв'яжіться з нами — ми підготуємо оптимальне рішення під ваш стек.







