Legal
Data retention schedule
Every place data is held, how long it stays, and what removes it. Derived from the schema, so it matches the code rather than describing an intention.
Last updated Updated August 18, 2026
The principle
The shortest retention schedule is the one for data that was never collected. For an individual technician there is no server-side record at all, so most of this page is about a device you control and can wipe in ten seconds.
Where data does reach us — cohort seats and instructor accounts — the lifetime is written into the database row rather than applied by a scheduled job, so it holds even if a job fails.
On your device
| Store | Contains | Retention | Deleted by |
|---|---|---|---|
| profile | Certification path, exam date, theme, haptics and reminder settings, alias, content version, install-scoped random id. | Until you uninstall or clear the app’s data. | Uninstalling the app. There is no server copy. |
| attempt | Every answer: question id, subject area, right or wrong, milliseconds taken, mode, timestamp. | Until you uninstall. Never pruned — the review ladder and the readiness estimate both need the history. | Uninstalling the app. |
| review_queue | Which questions are due, when, and the streak on each. | Until you uninstall. | Uninstalling the app. |
| mock | Mock exam attempts: item ids, start, deadline, submission, score, per-section result. | Until you uninstall. A submitted attempt is immutable so results reproduce exactly. | Uninstalling the app. |
| entitlement | What you own, its source, when it was last verified, any expiry. | Until you uninstall. Rebuilt from the store on Restore purchases. | Uninstalling the app. |
| outbox | Queued cohort pings, question defect reports and code redemptions waiting for a connection. | Until delivered, then removed. Until you uninstall if never delivered. | Successful delivery, or uninstalling the app. |
| clock | A single high-water timestamp guarding the review scheduler against clock changes. | Until you uninstall. | Uninstalling the app. |
| Scheduled notifications | Up to eight local reminders computed on the device from your exam date. | Until they fire, the exam date changes, or reminders are switched off. | Switching reminders off, changing the date, or uninstalling. |
The question bank itself is a read-only database shipped inside the app. It contains no personal data and is replaced wholesale by a content release without touching anything above.
On our servers
| Store | Contains | Retention | Deleted by |
|---|---|---|---|
| instructor | Email address and organization name of somebody who bought cohort seats. The only email address in the system. | Until the instructor asks for deletion. | A deletion request. Deleting the row cascades to cohorts, seats and pings. |
| cohort | Class name, optional exam date, number of seats paid for, Stripe payment reference. | Until the instructor deletes it or their account. | Deleting the cohort or the instructor. |
| seat | Eight-character code, the alias the student chose, bank scope, issue and redemption timestamps, a salted device hash. | 180 days from issue if never redeemed; 90 days from redemption otherwise. The expiry is written into the row, not applied by a cron job that could fail silently. | The instructor deleting the seat or the cohort, or a request naming the seat code. |
| progress_ping | Seat code, readiness, answered count, weakest subject area, server timestamp. Insert-only. | For the life of the seat. Rate-limited to one per hour per seat. | Deleting the seat, which cascades. Nothing else writes or reads it directly. |
| question_report | A question id, the content version, a reason from a fixed list, and up to 500 characters of free text. | Kept as a defect record. No account, no device identifier and no seat linkage, so it is not connected to a person. | Nothing automatic; it is anonymous engineering data. |
| rate_limit_bucket | A hashed client fingerprint (an HMAC of the IP address, truncated) and a counter. | Swept after two days by the weekly job. | The sweep. |
| content_release | Published question-bank versions, their eCFR snapshot and item counts. | Permanent. It is a release log and contains nothing about any person. | Nothing. |
| Instructor session cookie | A signed, HTTP-only cookie identifying a signed-in instructor. | The session. Cleared on sign-out. | Signing out, or the cookie expiring. |
Logs
Ordinary web-server request logs are produced by the hosting provider for the website, the instructor console and the cohort endpoints. They include IP addresses and request paths. They are operational, are not joined to any profile, and are not used for analytics.
Application logs deliberately do not record question text, answers, aliases or email addresses. The same scrubber that governs analytics events governs crash breadcrumbs.
With processors
Apple, Google, Stripe and RevenueCat retain purchase records under their own schedules; those records are theirs and we cannot delete them. PostHog and Sentry retain events and crash reports under the plan configured for them — neither is enabled in the current build. The sub-processor list.
What deletion actually does
- Uninstalling the app removes every row in the device table above. There is no server copy for an anonymous user, so that is the whole deletion.
- Deleting a seat removes the seat row and, by foreign key cascade, every progress ping attached to it.
- Deleting a cohort cascades to its seats and their pings.
- Deleting an instructor cascades to their cohorts, seats and pings. The only email address in the system goes with it.
- Question defect reports are not deleted, because they carry no identifier of any kind — no account, no device hash, no seat.
Requests: privacy@superheatprep.com. The deletion clause in the terms.