From Mobile to Full Stack

It's been almost three years since I've been building apps. Despite still feeling like a beginner in many areas, I've explored a decent number of technologies by now, so I thought I'd share my journey so far when it comes to the tools of the trade.

Early Days

I began with native iOS development. Things seemed straightforward. As you would expect with a set of platforms built by one company.

Most of the tech needed to build an iOS app, I rarely had to think about. The choices were simple:

  • Auth? For offline only apps, you don't even need accounts. When auth is needed, Firebase is pretty straightforward to set up.
  • Database? Firestore, again, straightforward enough. Core Data if the app is limited to Apple platforms. If the data is not very large (it usually isn't), just use a JSON! Or Christian Selig's cool library TinyStorage.
  • Sync? If you're using Firebase, you're covered. If not, iCloud is easy to get started with, and seamless!
  • Security? App data is usually in a sandbox. The most I had to do was make sure any API keys were obfuscated using the project's build configuration.

Hitting Walls

For a lot of projects, the stack described above is perfectly fine. But things changed when some of my projects became more ambitious. Especially when I wanted to add cross-platform capabilities to the mix.

It no longer felt like the right set of choices:

  • Auth and Database - Core Data has limitations when it comes to searching - think stuff like fuzzy find, typo tolerance etc. Plus, it's limited to Apple platforms only. SwiftData is too new still, and has the same limitations.

    Firestore is also limited with search. The service apparently doesn't work well in China, and I've had other issues when using it in app extensions like iOS widgets. Serverless is fun and easy, but you usually either run into limitations, or cost goes up a lot at scale (there are companies looking to solve this). Migrating away later would present its own set of challenges.

  • Sync - Firebase works great for sync, but has its drawbacks if you structure your data to save costs (high network usage in my case). It's not built for offline-first apps either. iCloud Sync feels complicated to set up if you're not using Core Data or SwiftData, which I'm hesitant to due to the reasons I've described above.

  • Security - Storing secrets on the client side is anyway considered an anti-pattern - so the obfuscation method is not ideal for production apps at scale - the secrets are still part of the bundle. Apparently the only really 'secure' way is to have secrets on a properly secured server (or serverless backend). Plus if you're gonna interact with a server, you need rate limiting, server-side authorization, validation and so on to make sure no one abuses outgoing requests. I'm sure there are other things to mention here that I'm either forgetting or don't know about.

Adapting

Given these issues, it was time to step outside of my comfort zone and learn a bunch of new stuff again.

It's not really 'new' stuff though. It's actually just old, boring stuff that's been around for a while. Stuff that may not be easy or straightforward to learn (at first), but is by all accounts time-tested, reliable, and flexible, with a large existing support and knowledge base.

Here's what I've landed on so far:

  • Authentication - I'm leaning towards session-based auth for both web and mobile apps. I considered using token-based auth on mobile, but implementing and maintaining two different auth mechanisms feels unnecessary work at an app's early stages.
  • A relational database - On the server, PostgreSQL could be a good choice. Versatile, very flexible, has a large amount of information online for anything you might run into, great default search which is also extensible etc. Similarly for local storage of the data on mobile, a SQLite database (wrapped by a library that's not Core Data or SwiftData) should be sufficient - GRDB has been great so far.
  • Sync - This one is a bit trickier. I might need to write custom logic for the local SQLite database to sync with the PostgreSQL instance on the server (blasting that comfort zone to smithereens - again 😭).
  • Security - I'm learning about rate limiting, authorization, middleware, and other tools to improve security. Setting up and securing servers though? I'll leave that to the pros - Laravel Forge, Render and similar services can help here.

A lot of the stuff above is simplified by web frameworks like Django, Laravel, Rails and more. All seemingly time-tested, reliable and flexible tools themselves.

Trying to understand all of this might be (probably is) against the MVP mentality when it comes to mobile apps (it's all taking a really long time for me to really get the hang of and remember). But I'm betting on the fact that like anything, you get faster and better at it with time.

Only this time, I hope to run into fewer limitations and fewer debugging issues, while having more confidence in my code. Time will tell.

There's this article called Choose Boring Technology. I found myself agreeing heavily with its message. Give it a quick read if the title interests you.

In any case, even if learning this stuff is often quite frustrating, it's quite satisfying when things finally click.

It's worth it. At least for now.