← All articles
8 min readPrivacy,Data Deletion,Pipeda,Engineering

How Flowo Handles a Deletion Request, Step by Step

By Mykhailo Boichuk · Chief Technology Officer

In short

In Flowo, the planning app from BBMM Technologies, a deletion request runs as two operations that report separately. The backend scrubs the install's device record, then the app deletes its local stores and discards the encryption key. Local erasure runs even when the server cannot be reached, and records held outside the app, such as store payment records, are handled by an email request.

Two boundaries, reported separately

A deletion in Flowo is coordinated by one small class that treats the server and the device as separate boundaries. It calls the server first, because that call needs the device credential and the credential is about to be erased. It catches any error from that call and then runs local erasure regardless.

The result holds two booleans, one for the server and one for the device. The screen maps them to three end states: complete, erased locally with the server unconfirmed, and failed. In the second state the message says the device is clean and the server could not confirm yet. In the third, a button retries.

The control sits in the Legal and Privacy group of Settings and asks twice, first in an action sheet and then in a final dialog. Before erasure starts, the app replaces its entire widget tree with a standalone screen, so no data-bound widget can rebuild against a store that is being deleted. Back navigation is disabled on that screen, and the status text is a live region for screen readers.

What the server deletes

The backend exposes one privacy operation for an install, an authenticated DELETE on the device record. A request without a valid device token receives 401, and a successful one returns 204 with no body.

The handler does two things. It deletes the attestation key records linked to the device. It then overwrites the device record with a tombstone whose platform reads deleted, whose plan is free and whose revoked flag is true.

The tombstone has a specific job. The access token that authorized the deletion would otherwise stay valid until its natural expiry, and the revoked flag closes that window on the next request. A later reinstall generates a new UUID and attests as a new device.

On the client, a 401 causes one retry with a fresh token. After a confirmed deletion the app drops its cached token and resets its attestation state. Daily usage counters are separate items that carry an expiry timestamp two days after their reset.

The order of local erasure

Local erasure is a fixed pipeline, and the order exists because later steps destroy what earlier steps need.

  1. 1.Write a final audit entry that records whether the server deletion was requested.
  2. 2.Stop both analytics providers, reset the analytics identity, replace the session id and clear the local analytics markers.
  3. 3.Cancel every scheduled notification.
  4. 4.Clear the snapshot that home screen widgets and shortcuts render from.
  5. 5.Delete recovery backups, captured media, log folders, avatar files, temporary voice recordings and earlier export files.
  6. 6.Clear the app's preferences and close the database.
  7. 7.Delete every registered store by name, then six store names retired by earlier releases.
  8. 8.Sweep the storage directory for any remaining database or lock file.
  9. 9.Delete the master encryption key from the Keychain or Keystore.
  10. 10.Reset the attestation state and delete the device identity.

The widget snapshot gets its own step because it is user content kept outside the encrypted stores. Deleting the stores does not reach it, so it is cleared by a hook that needs no running service.

The sweep in step eight covers files that no list names. A store written by a retired feature, or by a newer build than the one running, would otherwise survive deletion by name. The sweep is restricted to the database's own file extensions, since the same directory holds media that step five handles.

Required and best-effort steps

Each step in the pipeline is declared as required or best-effort, and the two kinds fail differently. A failed best-effort step is logged as a warning and forgotten. A failed required step is logged as an error and its label is added to a failure list.

The pipeline continues after either kind of failure. If the failure list is non-empty at the end, the service throws an exception that names the failed steps, and the screen shows the failed state with its retry button.

Calls into SDKs and system services are best-effort: stopping the analytics providers, resetting their identity and cancelling notifications. A provider that returns an error must not make a finished local wipe report that data remains. Steps that remove user content or identifiers are required. That covers the widget snapshot, recovery backups, preferences, the encryption key, attestation state and the device identity.

Why the key is deleted last

The stores are encrypted with one AES-256 key held in the platform's secure storage, and deleting that key makes any leftover ciphertext unreadable. That property is the reason the key goes near the end.

The key is deleted only when every store deletion succeeded. If one store file could not be removed, the service keeps the key and logs how many deletions failed. The person can then retry, and the app can still open the store it has to delete.

Two tests pin this behaviour. One asserts that the key is retained when any store deletion fails. The other asserts that the key is deleted once every store is gone.

Export before deletion

Flowo offers an export in the same settings group, and the data rights page on flowoapp.com advises using it before erasing. The export is one JSON file with the schema name flowo.export.v1.

It contains the 21 stores that the app's storage registry marks as eligible, each as a list of keys and values, plus a metadata block with the export time and the consent version. It leaves out the master key and everything in secure storage, such as tokens issued by the backend.

The file is written to the temporary directory and handed to the system share sheet. Earlier export files are deleted before a new one is written, and the new file is deleted when sharing ends. The audit log records the export with its size in bytes and no content.

The export has no matching import. It is a copy for the person's own records.

Requests the app cannot complete

The in-app control reaches the device and our backend, and some records sit beyond both. The data rights page on flowoapp.com explains the remaining paths.

Payment records for a subscription are controlled by Apple or Google. The page also states that removing the app does not cancel a subscription.

Records that BBMM Technologies controls outside the app, such as website forms, are requested by email to the Privacy Officer. The page asks for the request type and the product surface involved.

Flowo has no account, which sets a limit that we state on the page: after the local identity is erased, we may be unable to match an app installation to a record. Withdrawing analytics consent stops future collection. For historical pseudonymous events, the page says a request is routed through the provider's process where a record can be matched.

Key takeaways

  • Flowo's deletion coordinator calls the server first and then runs local erasure even if the server call fails.
  • The backend deletes the install's attestation keys and replaces the device record with a revoked tombstone, so the authorizing token stops working.
  • Local erasure deletes registered stores by name, six retired store names, and then any remaining database file in the storage directory.
  • The AES-256 master key is deleted only after every store deletion succeeds, so a failed erasure can be retried.
  • Each erasure step is marked required or best-effort, and only required failures put the screen in its failed state.
  • The export is one JSON file covering 21 stores, and it is deleted from temporary storage after sharing.

Frequently asked questions

How do I delete my Flowo data?
Open Settings, go to the Legal and Privacy group and choose the delete control. The app asks for confirmation twice, removes the install's server record and then erases local data and the encryption key. The final screen says whether both parts finished.
What happens if I delete my data while offline?
The local erasure still runs. The screen reports that the device is clean and that the server could not confirm the remote deletion yet. The message advises retrying from a connected device or contacting support.
Does deleting Flowo data cancel my subscription?
No. Subscriptions are billed by the App Store or Google Play, and those payment records are controlled by the store. A subscription is cancelled in the store's own settings.
Can I get a copy of my data before deleting it?
Yes. The export control in the same settings group produces one JSON file through the system share sheet. It covers 21 local stores and leaves out the encryption key and backend tokens. There is no import, so the file is a record and cannot be loaded back into the app.
Why does a deletion tool delete the encryption key last?
Deleting the key makes any remaining encrypted file unreadable, including one the app still needs to open in order to delete it. Flowo keeps the key until every store has been removed, so a partial failure can be retried cleanly.

References

  • Flowo data rights page
  • BBMM Technologies Privacy Policy
  • Regulation (EU) 2016/679 (GDPR), Article 17, Right to erasure
  • Personal Information Protection and Electronic Documents Act (PIPEDA), Schedule 1, principle 4.5, Limiting Use, Disclosure, and Retention
  • Apple Developer Documentation, Keychain Services
  • Android Developers, Android Keystore system

About the author

Mykhailo Boichuk

Chief Technology Officer

Mykhailo builds the systems behind the apps. He works on macOS and iOS performance, and on the sync problems that come with software that has to run offline.