What leaves your phone, and what doesn't.
Struggle is a supportive AI companion. This policy describes what the app actually does with your data — not what a privacy policy usually says. Where a claim would be convenient but untrue, it is not here.
The short version
- Your conversations are stored on your phone, not on our servers.
- To write a reply, each message is sent through our server to an AI service provider. Nothing is generated on the device.
- We never write conversation transcripts to a database. Our servers keep a small profile row, the saved continuity steps you explicitly choose, a daily message counter, expiring request-control records containing no message or reply, and a minimized billing reconciliation ledger.
- There is no named sign-up account, email address, phone number, or password. The app uses an anonymous identity tied to this installation.
- Struggle has no advertising SDK and does not track you across other apps or websites. In builds where saved-step analytics is enabled, it sends Amplitude five content-free events about that feature — never chat or saved-step text, your name, or a stable person or device identifier. See exactly what those events contain.
- RevenueCat receives the subscription data needed to check an entitlement and restore a purchase. It does not receive your conversations. The details are below.
- You can erase everything from inside the app, without contacting anyone.
What stays on your phone
Your chat history lives in the app's own storage on your device. That includes the full text of every message you send and every reply you receive, the conversation titles, the name you chose, the support focuses you picked, a local copy of the steps you explicitly ask Struggle to keep in mind, and your local message counters. Conversation transcripts stay on the device unless you choose to export them. Saved continuity steps are also synchronized with our server as described below. The synchronized copy is available for recovery only while this installation retains the same anonymous identity; it is not a portable named account. Device storage is excluded from backups and written with file protection on, so it is not copied into an unencrypted backup.
If you delete the app, that device storage goes with it. Uninstalling alone cannot send an account-deletion request to our server; use Settings → Delete account and data before uninstalling if you also want the synchronized copy and server records removed.
What leaves your phone, and when
Replies are generated by an AI, not by a person, and not on your device. When you send a message, the app sends the recent messages in that conversation, the name you chose, the support focuses you selected, and at most one active saved step that you enabled for future chats to our server, which passes them to our AI service provider so a reply can be written. Disabled or completed saved steps are not sent. This is the same disclosure the app shows before you finish setting up, and it is why nothing here promises your conversations never leave the phone.
Our current AI service providers are OpenAI and Anthropic, which process this content on our instructions in order to return a reply. We do not permit them to use your conversations to train their models. Provider credentials live only on our server; the app never talks to a model provider directly.
Under their standard API data controls, these providers normally may retain API inputs and outputs for up to 30 days for safety and abuse monitoring. A shorter or zero-retention period may apply where an account-specific reduced-retention arrangement is active. Data may be kept longer where required by law or permitted by the providers' applicable policies, including for security or abuse investigations. Struggle does not enable provider-side application storage for conversations.
What our servers store
Conversation transcripts are not written by Struggle to a database table, application log, or file. Recent messages pass through in memory to generate a reply and are not retained by us afterwards. The one enabled saved step included with a request may also pass through to the AI provider; the separately synchronized saved-step record is described below. Our database keeps only:
- an anonymous user identifier, created for you automatically the first time the app runs;
- the display name you chose, if you entered one;
- the support focuses you selected during setup (for example grief, work stress), which shape the tone of replies;
- your subscription status, and a daily message count with the date it belongs to, so the free daily limit can be enforced fairly.
- saved continuity steps you explicitly create: the short step text, an opaque local conversation reference, whether the step is active or completed, whether personalization is enabled, and creation, update, carry-forward, and check-in times. No chat transcript or AI reply is stored with the step;
- when you delete a saved step, we keep a content-free deletion marker until you delete the anonymous account. It contains only the anonymous user identifier, opaque step identifier, and server deletion time; the deleted step text is not kept. The marker stops older local state associated with that same identity from recreating the step;
- for a request sent to an AI provider, a content-free request claim containing two SHA-256 digests: one identifies the provider attempt and one identifies the logical quota request. The claim records only whether the attempt is in flight, retryable, or completed, an opaque token during its short in-flight lease (normally 60 seconds and always between 15 and 120 seconds), and lease, completion, creation, update, and expiry times. If the request consumes free-tier quota, a separate row stores the logical-request digest, usage date, resulting counter, creation time, and expiry. These records prevent concurrent or replayed provider calls, duplicate quota charges, and more than 20 new provider attempts in 60 seconds for one anonymous account. They contain no raw request or provider-attempt identifier, message, prompt, reply, or request payload. Both stop affecting decisions at their exact expiry: after 48 hours when the native app supplies its stable identifiers, or after 10 minutes for a legacy payload-only request;
- a minimized billing reconciliation ledger containing the anonymous user identifier, RevenueCat webhook event identifier and type, event time, production-or-sandbox marker, requested free-or-premium result, processing outcome, and processing time. A content-free retry record also keeps its source, state, observed tier, attempt count, next-attempt and short lease times, and a bounded internal error code until reconciliation completes. We store no raw webhook body, receipt, product, price, transaction, card, or Apple ID in these records.
Our hosting provider automatically creates limited platform and network logs so requests can be secured and failures investigated. In the current production configuration these records include the time, request path and method, status, duration, edge region, user agent, anonymous account and session identifiers, IP address, and coarse network-derived location. They do not include request or response bodies, message text, enabled saved steps, or AI-provider payloads. Struggle does not add custom logs containing that content. Platform logs are available only for the rolling retention period provided by the active hosting plan and are used only for reliability, security, and abuse investigation.
Product interaction analytics
When continuity analytics is enabled for a build, the native app sends Amplitude a small, reviewed set of events that show whether the “Resume from here” saved-step flow works — whether a step was suggested, saved, edited, resumed, or deleted. A resumed event records the finite check-in outcome, whether it was the first check-in, and whether it happened within 72 hours; the other events can include only short finite action, source, and status fields. It never includes chat or saved-step text, conversation or account IDs, your name, support focuses, or record timestamps. Screen views and other app events stay local-only.
Amplitude's ingestion API requires an identity field, so each event independently selects one of 128 aggregate routing shards shared by every installation. A shard is never persisted or derived from a person, account, or device; the same shard intentionally mixes unrelated events and is not a Struggle user identity. A fresh random insert identifier is used only to de-duplicate that request. The app sends no identify calls. It sends no stable analytics identity.
Struggle supplies no IP or location field in the event payload and adds no country, region, latitude, longitude, device, operating-system, or platform metadata. The HTTPS request still travels over the network to Amplitude; this statement describes the fields the app supplies, not the ordinary network transport.
Your account
Struggle signs you in anonymously. There is no email address, no password, no phone number, and no social login. The identifier is tied to the app on that device — it is not a profile of you, and we cannot use it to find you anywhere else. If you delete your data, that identity is deleted too, and the app starts again as a new guest.
Purchases
Subscriptions are sold through the App Store. Apple processes the payment; we never see your card, billing address, or Apple ID. We use RevenueCat to check whether a subscription is active and to restore purchases, which means RevenueCat and Apple receive purchase and entitlement information linked to an app-specific identifier. If billing information is unavailable, the app falls back to free-tier behavior rather than locking you out.
RevenueCat also uses purchase history and that custom app user ID for customer history, subscription charts, and experiments. Those are subscription analytics, not behavioral tracking across other apps or websites.
How this maps to Apple's privacy label
Struggle's app-level privacy disclosure covers eight data types. The answers visible on the App Store describe the version available there; the privacy manifest inside an analytics-enabled build also describes that build before it is released. All eight data types are treated as linked to the anonymous identity Struggle creates for the app, and none is used for tracking:
- Name, Health, and Other User Content are used for App Functionality.
- User ID and Purchase History are used for App Functionality and Analytics because RevenueCat uses them for entitlement checks, customer history, charts, and experiments.
- Product Interaction is used for App Functionality: the server stores the daily message count and its date so it can enforce and reset the free-message limit. Analytics-enabled versions also use Product Interaction for Analytics so the five content-free saved-step lifecycle events described above can show whether that feature works.
- Coarse Location and Other Diagnostic Data are used for App Functionality. Coarse Location means approximate location metadata derived from the connection IP in Supabase's platform logs, not GPS or a location permission. Other Diagnostic Data means technical request metadata such as path, method, status, duration, edge region, and user agent. Supabase creates these records for reliability, security, abuse investigation, and regional request routing — never for advertising or tracking.
-
Those two types are not marked for Analytics. The native release
uses a reviewed custom HTTP V2 sink rather than Amplitude's iOS
SDK and does not set the API's
ipor$remotefield, or send city, country, region, GPS, device, operating-system, or platform fields. The ordinary HTTPS connection still exposes a source IP long enough to operate the connection, but Struggle does not ask Amplitude to store it as an event field or derive event location from it. RevenueCat's current Apple App Privacy guidance likewise classifies its SDK as collecting neither location nor device diagnostic data. Amplitude therefore accounts here for Product Interaction Analytics. Any service provider's separate network or security processing of connection metadata remains operational processing for reliability, security, and abuse prevention; it is not used to evaluate user behavior.
Who processes data for us
- Supabase — database, anonymous authentication, and the server function that talks to the AI providers.
- OpenAI and Anthropic — generating replies from the message content described above.
- RevenueCat and Apple — subscription status, purchase validation, and app distribution.
- Amplitude — only when continuity analytics is enabled, aggregate product interaction analytics limited to the five saved-step lifecycle events above, without message content or a stable person, account, or device identifier.
- Vercel — hosting these public pages.
These providers act on our instructions under data-processing terms. Some of them process data outside the European Economic Area, including in the United States; those transfers rely on the European Commission's Standard Contractual Clauses or an adequacy decision.
Why we are allowed to process it
- To provide the app you asked for (performance of a contract): handling your messages so replies can be generated, keeping your subscription working, enforcing the free daily limit.
- Your explicit consent: messages, saved steps, and chosen support focuses can reveal health or emotional-state information. Before the first chat, the welcome screen says that messages, your chosen name, and at most one saved step you later enable are processed by the AI providers, and that tapping Continue means you agree. On the support-focus step, you make separate affirmative choices; “not sure yet” is available if you do not want to name a specific topic. We rely on those choices under Article 9(2)(a) when the content includes special-category health data. You can stop future processing by not sending more messages, disabling or deleting a saved step, changing your support focuses, or deleting the account. Withdrawing consent does not undo processing already completed lawfully.
- Our legitimate interest in keeping the service reliable and secure and understanding whether the saved-step feature works: error diagnostics, the five aggregate lifecycle events above, abuse and rate limiting.
How long we keep it
Conversations are kept on your device until you delete them or delete the app; we set no expiry on your behalf. The profile row, daily counter, and saved continuity steps are kept until you delete the anonymous account; uninstalling the app by itself does not notify our server. When you delete an individual step, its text is removed but the content-free deletion marker described above remains until you delete the anonymous account. Quota digests and provider request claims stop affecting decisions after their exact 10-minute or 48-hour expiry; expired rows are physically removed opportunistically in batches of at most 200, so physical deletion may happen later. Message transcripts are never retained by us at all. During normal reconciliation activity, completed billing rows older than 90 days are removed opportunistically. Pending retry rows remain until they reconcile or the account is deleted. Because cleanup runs with billing work, 90 days is an operational target, not an absolute maximum, for completed rows. Quota rows, provider request claims, and all billing rows are also deleted with your anonymous account. Purchase records are kept separately by Apple and RevenueCat under their own retention rules, since they are also needed for tax and refund purposes. When continuity analytics is enabled, Amplitude keeps the event-scoped interaction events under our configured retention setting and its data-processing terms; because the stream has no account or device identifier, it cannot be retrieved as an individual user's history.
Deleting everything
Open Settings → Delete account and data in the app. The app first asks our server to delete your profile row and anonymous account; that deletion also removes its saved continuity steps, content-free deletion markers, quota ledger, provider request claims, and billing reconciliation rows. After the server confirms that deletion, or confirms there is no linked account, the app clears the conversations, profile, and usage records stored on the device. If the server result cannot be confirmed, nothing on the device is cleared: Settings stays open, explains that the deletion did not finish, and lets you retry with the same account identity.
Deletion cannot be undone, and it does not cancel a subscription: manage or cancel that in your Apple ID subscription settings. You can also email support@struggle-app.com, but the in-app button is faster and needs no reply from us.
Your rights
If you are in the EU or UK, you have the right to access your data, to correct it, to erase it, to restrict or object to processing, to data portability, and to withdraw consent at any time. Because your conversations are on your device and not on our servers, the in-app controls are the most direct route: your chat history is already in your hands, and Delete account and data exercises erasure without asking us for anything.
For anything the app cannot do for you, write to support@struggle-app.com. You also have the right to complain to your local data protection authority.
Tracking and sale of data
Struggle does not sell personal data and does not share it for advertising. There is no advertising SDK or cross-app tracking SDK in the app.
When a build enables saved-step analytics, a custom, content-free stream limited to the five lifecycle events described above goes to Amplitude. Each event chooses one of 128 aggregate routing shards shared by every installation; the shard is not assigned to an account, person, or device. RevenueCat's subscription customer history and charts use the custom app user ID and purchase history described above. Neither service is used to follow someone across other apps or websites.
The privacy manifest in an analytics-enabled build marks Product Interaction, User ID, and Purchase History for Analytics as well as App Functionality. The App Store privacy answers are updated to match the version available publicly; all eight types are treated as linked and none is used for tracking.
Children
Struggle is for adults, 18 and older, and is being submitted to the App Store with an 18+ age rating. It is not intended for children. If you believe a child has provided personal data, contact us so we can review and remove it.
Safety
Struggle is not therapy, diagnosis, medical care, or emergency support. If you may be in immediate danger, contact local emergency services or a local crisis hotline. See how safety works for what the app does and does not do when a conversation touches a crisis.
Changes
If this policy changes in a way that affects what leaves your phone or what we store, the date at the top changes and the app's own data screen is updated to match.
Contact
The developer named as the seller on Struggle's App Store listing is the controller of the data described here. Privacy questions, requests, and complaints go to support@struggle-app.com.