Blog
Build in Public
April 9, 20265 min

I removed anonymity from my app, and it was the right call

I spent weeks building an anonymous authentication system that allowed TAMSIV to be used without an account. It was elegant, it worked well, and I was proud of it. This week, I deleted it all. Here's why it was the right decision.

Key takeaways

  • Anonymous sessions created zombie accounts that were impossible to track and complicated data security.
  • Mandatory registration simplifies code, improves conversion tracking, and protects user data.
  • A modal flash bug for the T&Cs was discovered and fixed immediately, thanks to better profile lifecycle control.
  • Version 1.04 (build 39) incorporates these three changes for production.

Why I removed anonymous authentication

When I launched TAMSIV in alpha, lazy registration was a no-brainer. According to AppsFlyer, 40 to 60% of users abandon at registration. By removing this friction, I thought I would maximize retention. And it worked, for a while.

But in production, the reality is different. Anonymous accounts accumulated in the database. Dozens of accounts without email, without a means of contact, without the possibility of recovery. The metrics on the admin dashboard became unreadable: it was impossible to distinguish a real user from a curious person who opened the app for 30 seconds.

The security problem was even more concrete. An anonymous account is an account with a UUID and data, but without a verifiable identity. If someone lost their phone, their tasks and memos disappeared with it. No email for recovery. No password for protection. Just an ephemeral token on a device.

How did this decision simplify the code?

[PERSONAL EXPERIENCE] By removing anonymous sessions, I eliminated a surprising number of conditional paths in the code. No more if (isAnonymous) in services. No more anonymous to real account migration logic. No more automatic cleanup of zombie accounts after 30 days.

Commit 7a0101d touched the entire authentication flow. On first launch, the user now lands on a registration or login screen. It's simpler, more predictable, and ensures that everyone who uses the app has made a deliberate choice.

Is there a risk of losing users during registration? Probably a few, yes. But those who register are engaged users. And that's exactly the type of metric we want to track in production.

The modal flash bug that no one had noticed

While testing the new authentication, I discovered a vicious bug. Every time the app launched, the terms and conditions modal appeared for a fraction of a second before disappearing. A quick, almost subliminal flash. The kind of thing you don't consciously notice, but which gives an impression of lack of polish.

[ORIGINAL DATA] The problem was with the timing. The app was loading the user profile from Supabase, and during this loading, the terms_accepted field was temporarily null. The modal component interpreted this null as "the user has not accepted the T&Cs" and displayed itself. A few milliseconds later, the profile arrived with terms_accepted: true, and the modal disappeared.

The solution in commit 8979543: wait for the fresh profile from the database before evaluating the modal's state. No profile loaded = no decision = no flash. Simple, but it had to be found. This type of bug does not reproduce in automated tests because mocks return the profile instantly.

Why bump a version for "just" 3 commits?

[UNIQUE INSIGHT] When building in public, the temptation is strong to group many changes into a single release to make it seem impressive. I did the opposite. The bump to version 1.04 (commit d900d21, versionCode 39) contains only these three changes. And that's intentional.

An authentication change is the kind of modification that can break things in subtle ways. A user who had an anonymous account, what happens when they update the app? Are tokens invalid? Is the profile accessible? By isolating this change in a dedicated release, debugging is simple: if something breaks, I know exactly where to look.

Small, frequent releases are better than large, rare releases. This is a principle I've applied since the beginning of TAMSIV, and it has saved me many sleepless nights. Each build is a testable snapshot. Each deployed version has a clear scope.

What this changes for users

In practice, the change is minimal for someone who was already using TAMSIV with an account. Nothing changes. Tasks, memos, groups, everything remains in place.

For new users, the experience is different but not necessarily worse. Instead of landing directly in the app, they go through a registration screen. Email, password, done. And from there, their data is secure, synchronizable across multiple devices, and recoverable in case of phone loss.

The QR code authentication system for the web app now works for 100% of users, not just those who took the time to create an account. This is a concrete gain in UX for the desktop version.

The lessons of a solo dev who changes his mind

Changing your mind about a technical decision is uncomfortable. I wrote an entire article about the benefits of lazy registration. And today I'm doing the opposite. Is it embarrassing? A little. But it's also the reality of development: what's optimal in alpha isn't necessarily optimal in production.

In alpha, with 12 recruited testers, anonymity reduced friction. In production, with real users who expect their data to be secure, registration is a minimum. The context has changed, so the decision changes.

If you're building a product and you're hesitating between these two approaches, my recommendation is simple. In pre-launch, lazy registration is great for validating your product. In production, mandatory registration is wiser. You can always offer a generous free trial to compensate for the friction.

FAQ

Do existing anonymous users lose their data?

Anonymous accounts that had been migrated to real accounts (with email) are not affected. Only accounts that remained purely anonymous, without an associated email, can no longer log in. A cleanup of these orphaned accounts is planned.

Does registration take long?

Two fields: email and password. No SMS verification, no captcha, no lengthy form. The goal is to stay under 30 seconds between opening the app and first use.

Did the modal flash bug affect security?

No. It was a purely visual problem. The T&Cs modal briefly appeared and then disappeared. No data was exposed and the conditions remained accepted in the database. It was a polish defect, not a security one.