Historical context¶
Some things in the database or other places might not make sense without some historical context. Here's a brief overview of the Settle Up history that will hopefully clear things up.
Ancient history¶
Settle Up started as a very loose collection of apps with a shared backend. Each platform was designed and developed independently with different UI, branding and monetization.
Android + backend¶
Settle Up started as an Android app & appengine backend. Most importantly, the AppEngine (datastore) saved diffs of data – each change on client only saved this diff, so reconstructing the current state meant going through all changes and applying them in order. The Android app was freemium with receipts and no-ads when you bought the IAP.
iOS¶
iOS went through several major rewrites. It launched as a "leather" app (MUST-SEE video), which was paid. Later, it was rebranded and launched as Settle Up 7, which was a separate app, paid again.
Windows Phone¶
Windows Phone app was always free and had fewer features than the other apps.
Web¶
Made as a polymer app, it was also always free and had limited features.
Firebase era¶
With Firebase, everything changed. As Android and iOS had many (even paying) users, they had to be migrated to Firebase. On top of that, Android supported offline groups – without proper migration they would be lost during the update. Windows Phone & Web versions were completely rewritten from scratch. Windows app was eventually discontinued. Web app, now written in Angular, is up to par with Android & iOS.
Database¶
Due to existing userbase, we had to migrate data from AppEngine to Firebase. And because not all users would update at once (due to gradual rollout and iOS development & release lagging behind Android) the process had to be realtime & two-way.
When someone from a group started using the new app their groups would be migrated to Firebase and AppEngine would start acting as proxy to Firebase. To know which entities were already migrated and which were new, all firebase entities were assigned
migrated: true
property. This is still used today by backend to track entity changes and should be ignored by apps.
The migration process had to do everything the apps did to get to the current state of entities (database stored only diffs). This process turned our to be pretty hard due to missing or corrupt data. There was a secondary service written in Go which did this.
Originally, migrations ran under a service account but after a major incident which nuked part of Firebase Database we switched to an authenticated account which was guarded by database security rules.
The migration also seeded the users and permissions. Users' part of migrated group were created in Firebase and added to have permission to the group. Those were called legacy users because they didn't really exist in Firebase Auth. When such a user would later start using the app they would be created as actual Firebase Auth user and matched with their legacy entity, which would get deleted.
Migrations are now disabled and the codebase is cleaned from them.
Monetization¶
Settle Up now has unified monetization model but still has to reflect previous purchases. Android users who bought "premium" previously have no ads. iOS was a paid app from the start, users who bought it also got rid of ads and unlocked adding receipts.
At first, we also offered in-app trials (not related to any store, only stored in our DB) but this was abandoned.
Sharing links¶
A big part of Settle Up is the sharing link used to invite users to groups. Originally this was a Firebase Dynamic Link, which offered several benefits:
- Opens app if installed with group preview
- Opens store if not installed
- After installation, it continues to the group in the original link
- Fallback to web app (e.g. on Windows)
Since dynamic links were decommissioned we migrated to our own solution, links are hosted on link.settleup.app. During the years, the domains changed, therefore the backend now automatically migrates old links to new ones. More details here.