I started building REST APIs a few years ago because I was desperately in need of a back-end engineer, and it seemed easier for me to just do it myself. That, of course, is how all classic software engineering problems begin and where many startups end, but I thought: How hard could it really be? After all, I’d already finished my mobile app, and I’d designed the necessary algorithms already. I just needed them to run on a server.

Predictably, that’s where things got tough. Because for every action you take in an app, you need a corresponding endpoint on the server — and usually multiple methods for each endpoint — so that your app can communicate what it’s doing with the server. And for every bit of data you generate beyond a simple button press, you also need a structured way to communicate that data back to your server, which you usually accomplish by converting data that starts in SQL or as properties on an object into JSON. So, you end up with many endpoints, much serialization code, and many more lines of code for every time you changed your mind about what you want to send or receive from the server.

In short, making your mobile app talk to your server is never an easy thing. And the greater your ambitions, the more complex and fragile this dance becomes.

In principle, this doesn’t seem like a necessary state of affairs. Often, we take technologies and accept their limitations as fundamental, when really we’re just using the wrong technologies in the wrong contexts. When it comes to building modern mobile apps, it’s high time we accept that we’re victims of server-side and mobile technologies that simply do not like speaking to another.

It’s not just development time that gets eaten up by these incompatibilities, either. It’s also the performance of our apps. Every time our apps have to translate another bit of data from JSON to something useful, we slow down the app. Users don’t like that. We also have an opportunity cost: Every joule of energy used to communicate with the server means you can no longer use that joule to do something that the user will actually notice and appreciate.

But there’s hope. If code complexity and data incommensurability are the fundamental problems that mean mobile apps suffer under the weight of the RESTful APIs on which they rely, then that points to our solution, too. Let’s make things simpler — by speaking the same language.

SQL databases seem to be very frustrating when you have to convert SQL data constantly into an object-oriented language — whether it’s Python on your server or Java on your app. So maybe we can simply get rid of SQL-based databases altogether. The easiest solution would be to just use a NoSQL database on your backend, so that you can drop JSON documents right into it without any serialization code.

But you could also free yourself of the pain of SQL and its related ORMs on the mobile end app if you use an object database. That way, you simply define your schema in a class, and the data you create exists as instances of that class. You work with native objects the whole time on the app, and serialize them only when you have to communicate with the server.

Ultimately, the problem is that you have to move from SQLite in your app, to a native model class, to JSON that you can send to your server, into another model class, and finally into SQL again, before your data finally comes to rest on your server. That’s a long trek, and we owe it to our users and our developers to cut out the unnecessary steps that our data takes.

Beyond limiting the number of endpoints or serialization and deserialization steps, you can move away from the request-response cycle and towards seeing data as soon as it’s available by adopting reactive principles. Mobile apps bring with them an expectation of constant connectivity, but realizing that with constant HTTP requests can introduce a lot of overhead. Also, you’re making these requests blindly — you don’t actually know if there’s any new data on the other side. A modern reactive app starts by moving to streaming, so that data gets to your device whenever it’s available. Data is pushed to you, instead of pulled from your server.

With a guarantee of fresh data, reactivity means that you can let data do the hard work of telling your app what to do next. Instead of refreshing your UI in a callback of a successful request, reactive programming means tying your UI to your data. Whenever new data comes in, the UI automatically adapts to those underlying changes — no need to call an update method. Now, you’ve got fresher data, and much less code meant to wrangle and display it.

RESTful APIs give you a predictable, well-defined way to exchange information between your client devices and your servers. But doing it in a way that’s likely to result in the best experience for your users isn’t as simple as getting your app and your server to talk. It involves making sure the right data is being sent as economically as possible, as soon as it’s available, and being displayed to your users the moment it shows up.