If a learner quits your app tomorrow, can they take their progress with them, without begging support or receiving a useless PDF?
That’s the practical test behind data portability. It’s not just a legal concept. It’s also a product quality signal: your data model is coherent, your exports are complete, and your users can leave without friction.
This quick check is built for product teams, privacy leads, and mobile QA. It also works for power users who want proof, not promises.
What “data portability” should look like in a language app
At a high level, data portability means a user can get a copy of their personal data in a format that’s easy to reuse. Under GDPR, the right is often discussed in the context of Article 20 and its requirements around receiving data in a structured, commonly used, machine-readable format. For a plain-English walk-through, see GDPR Article 20 portability examples. (For decisions, always check the official legal text and your counsel’s view.)
In language apps, portability usually includes more than “account info.” Your app may hold years of learning history and user-generated content, such as:
- speaking practice recordings
- conversation transcripts with tutors or bots
- corrections, feedback, and rubrics
- spaced-repetition schedules and review history
- saved words, custom decks, and notes
It helps to separate three ideas that often get mixed up:
- Sync (same account, same service): moving state between phone and web.
- Portability (user takes data away): exporting data so it can be used elsewhere.
- Deletion (user exits): removing or anonymizing data after the user leaves.
Portability starts with knowing what you collect and why. If you need a fast way to map that inventory from the UI, use this guide to check language app privacy settings before you judge your export.
A good export feels like moving house with labeled boxes. A bad export feels like a photo of your living room.
The 15-minute data portability check (fast, repeatable, and honest)
Set a timer, use a test account with real activity (including speaking and writing), and try to export from the same surfaces users use (mobile and web). This is the order that catches the most issues quickly.
- Minute 0 to 3: Find the export path like a user would
Look for “Download my data,” “Export,” or “Privacy tools.” If the only path is “email support,” note that. Also note whether the feature is inside the app, web-only, or hidden behind a help center flow. - Minute 3 to 6: Trigger the export and capture the promises
Start an export. Screenshot the confirmation and any stated timeline. If the UI claims “JSON” or “machine-readable,” you’ll verify that in a minute. If the export arrives by email, confirm it doesn’t require logging in again in a way that breaks for SSO users. - Minute 6 to 10: Inspect the file structure, not just the first page
Open the download. Count how many files and folders you got. Check whether it’s a ZIP with multiple assets (often a good sign), or a single PDF (often a bad sign). Confirm timestamps have time zones, and that identifiers exist to link related records (for example, transcript rows linking to lesson sessions). - Minute 10 to 13: Check for language-app “gotchas” (speech, feedback, SRS)
Look for audio, transcripts, corrections, and review scheduling. These are the first things teams forget, and the first things learners value. If your app uses spaced repetition, verify you export the schedule state (next due, interval, ease) or at least enough history to rebuild it. - Minute 13 to 15: Write down what a user can actually do with it
Ask one blunt question: “Could another app import this without custom engineering?” If not, document what’s missing (fields, formats, or relationships).
Here’s a compact “minimum viable export” map for language apps. Your app may have more, but missing items in this list usually cause user complaints.
| Data area | Example export fields | Why it matters |
|---|---|---|
| Account + identifiers | user_id, email (or hashed), created_at, locale, consent flags | Links everything, supports support and audit trails |
| Subscription + billing metadata | plan_name, renewal_date, purchase_channel | Helps users reconcile payments and history (without exposing full payment data) |
| Course enrollment | language_pair, placement_level, curriculum_version | Explains why progress looks the way it does |
| Lesson history | lesson_id, completed_at, score, mistakes | Core proof of learning activity |
| Vocabulary + saved items | saved_word, translation, tags, user_notes, source_context | Users often want to keep their personal word lists |
| Spaced repetition state | card_id, last_reviewed, next_due, interval, ease_factor | Without this, “continue elsewhere” becomes “start over” |
| Corrections + feedback | original_text, corrected_text, feedback_type, rater (human or model), timestamp | Captures learning value beyond right or wrong |
| Conversation logs | transcript, speaker_turns, prompts, message_timestamps | Users may need this for study or records |
| Speech recordings (if collected) | file names, format, duration, linked exercise_id | High sensitivity, high user value, often mishandled |
For broader implementation ideas (including transfer methods beyond one-off exports), the Data Transfer Initiative compendium is a useful reference.
Common portability failures that language apps run into
Most portability problems aren’t malicious. They come from product shortcuts that felt reasonable at the time.
“We exported it,” but it’s not reusable
A PDF progress report is readable, yet it’s rarely portable. The same goes for screenshots, email summaries, or “Your Year in Review” pages. Users can’t import them, filter them, or join them to anything.
Quick fixes that usually work:
- export CSV or JSON alongside any human-friendly PDF
- include stable IDs (lesson_id, card_id) and consistent timestamps
- keep text in UTF-8 and don’t strip accents or non-Latin scripts
Speech, transcripts, and feedback fall through the cracks
Speaking practice creates messy data: audio files, model scores, human ratings, and maybe transcripts. Teams often export only the final score and drop the recording.
That omission matters because speech data can be deeply personal. Even when you can’t provide raw recordings (for example, because they were never stored, or retention is short), the export should clearly state what exists and what doesn’t.
For a grounded look at how portability plays out in practice across industries, skim GDPR Data Portability: The Forgotten Right.
Progress won’t “travel” because it’s derived, not stored
A lot of learning state is computed, not saved, such as mastery scores, adaptive difficulty, or review queues built from many signals. That’s fine, until you export only the final number.
If you want portability without exposing internal ranking logic, export the user-level inputs and snapshots:
- review events with outcomes
- current SRS schedule per item (even if it’s approximate)
- user-created data that shaped the experience (saved words, notes, corrections)
Also check identity edge cases. “Sign in with Apple” plus email login can create two accounts with split histories, which makes portability look broken.
If you want to separate portability issues from plain sync bugs, run a quick 10-minute language app sync test first.
If you only fix 3 things (high impact, low drama)
- Ship a real machine-readable export: Provide JSON or CSV, not just PDFs, and document the schema.
- Include the hard learning data: corrections, feedback, transcripts, saved words, and SRS state (or enough history to rebuild it).
- Make it self-serve and verifiable: users should start an export in-app, then receive a clear confirmation and a reliable download link.
Portability also connects to offboarding. When a user asks for export, a deletion request often follows. If your flows are tangled, tighten them with this guide to delete a language app account fully.
Lightweight template to document your results
Use this small table in your ticket or risk log. It keeps debates factual.
| Item | Where tested | Result | Notes |
|---|---|---|---|
| Export entry point | iOS app / Android app / Web | Pass / Partial / Fail | Found under Settings > Privacy tools |
| Format | ZIP + JSON/CSV / PDF only | Pass / Partial / Fail | JSON present, but no schema doc |
| Speech + transcripts | Export includes media links/files | Pass / Partial / Fail | Audio missing, transcripts included |
| SRS schedule | next_due + interval present | Pass / Partial / Fail | History present, schedule not present |
| Corrections + feedback | included with timestamps | Pass / Partial / Fail | Missing rater type and exercise_id |
Conclusion
Data portability is easiest to ignore when things are calm. It becomes urgent when a regulator, partner, or power user asks hard questions. A 15-minute check gives you a clear snapshot: what you export, what you omit, and what a user can realistically reuse. Run it once per release cycle, and treat every “PDF-only” export as a product bug. Portability is a trust feature, and users notice when it’s real.
