How to select the right React Native database

Shares

How to select the right React Native database

Purvak Pathak
in Mobility, Product Engineering
- 25 minutes
React-native-databases

From established organizations to hot new startups, developers are using React Native to build cross-platform applications. Moreover, there is a pressure on developers to deliver offline-first and high performing application that can be scaled whenever needed.

To meet these challenges they have to choose the right technology stack including the platform, back-end framework, libraries and a database. Now, there are many databases available for React Native which offer offline sync, reliable performance, better security and tons of new-edge features.

Poorly chosen Database can lead to failures for your React Native application.

Recently Crisp, a live-chat startup, who built their hybrid application using Firebase had to switch after few months of release. From an infinitely scalable database Firebase became a living nightmare for them. Because of which they struggled with the releasing new features, and could neither implement complex business logic to local and server side database.

We have hand picked everything you need to know in order to select the right database for your react native app development.

Local database selection for react native applications

We will first start with local databases. The local databases considered in our evaluation are listed below:

  • RealM
  • Firebase
  • SQlite
  • PouchDB

Realm Database for React Native

Realm database was built from scratch for offline and real-time applications running on mobile and wearable devices. Realm is not an ORM or built on top of SQLite, it has its own database engine and doesn’t just rely on key-value stores.

That explains why developers prefer to use Realm while handling a large amount of data or for high-performance applications. Realm allows developers to undergo frequently mapping classes, tables, foreign keys or the fields.

Realm is an object-oriented database rather than a relational database. OO model makes it 10x faster than SQLite and saves you from running tons of query which is a common thing for a typical SQL database.

Offline Applications with Realm

Realm is a local database, and when combined with a client-side database such as MongoDB, DynamoDB or MYSQL; developers can easily interact with the data synced locally in the Realm database.

Aside from offline sync, Realm offers the following features for an app to work offline or without network:

  • Realm synchronization services run in the background to record and save the user interaction, and service requests locally. Once the device is online, it sends data back to the server and executes the tasks without hindering the user experience.
  • Realm has algorithms to handle the conflicts in the objects while syncing the data back to the server.
  • Offline queue support automatically re-dispatch user actions when the connection is back online.

Offline friendly with redux-offline

If you are looking for an alternative solution that implements offline-first architecture with realm for React native application then redux offline might give you a sigh of relief.

Redux offline fulfils almost every arbitrary requirements of offline-based architecture such as:

  • Implementing read-write network resilience
  • Support for optimistic data updates when offline and pessimistic UI state in opposite case
  • Enabling background synchronization
  • Migrating database schema versions
  • Enabling data caching and up-front data loading

The main idea behind using redux as the offline synchronized storage along with realm is to use redux as your database in which you can serialize data and inform your Database when it changes. As soon as your app gets internet connectivity, you tell it to read data from your local memory.

For this, you can use redux-offline which is a standalone persistent state data container that can work with any web application written in any language. The library is designed in a way so that it covers all the aspects of an offline-first app-based experience.

Security in Realm

Realm uses different encryption standards for each platform.i.e. For Android, they use AES-256 level of encryption and decryption of all the data stored locally.

Whereas for iOS applications, their encryption is based on the iOS CommonCrypto library, which protects the app data and passwords stored in the keychain. For windows applications, Realm uses Crypto library for encryption.

Each of these libraries can be used to generate a 64-byte of encryption keys, where each 4kb block of data is further encrypted with AES-246 cipher block chaining(CBC) method and then signed with an SHA-2 HMAC.

In my opinion, this approach can prevent most of the attacks and has been adopted by many industry leaders such as Amazon, and Netflix to build their mobile applications.

React Native app Performance with Realm

In terms of performance, Realm databases have been proven to run queries and sync objects significantly faster than SQLite and others. The objects stored in Realm can be accessed concurrently from multiple threads or sources, and it doesn’t require any specific lock configuration.

Realm was built from ground up for mobile, so they had the privilege to go beyond the traditional norms(SQLite). As opposed to Realm, SQLite is a generic database that was ported to mobile.

Everyone talks about “how fast Realm is”, but many don’t know the reason. The high performance of Realm can be better explained by:

  • Built-in storage engine which is written in C: Reduces dependencies and improves query performance
  • The traditional SQLite with ORM abstraction is leaky because ORM simply converts Objects and their methods into SQL statements. Realm, on the other hand, is an object database, meaning your objects directly reflect your database and it doesn’t convert the objects while doing read/write operations.
  • Zero-copy: The traditional way of reading data from a database leads to unnecessary copying into language level objects. Realm avoids this by mapping the whole data in-memory, using B+ trees and whenever data is queried, Realm simply calculates the offset, reads from the memory mapped region and returns the raw value.
  • Concurrency Control: Realm smoothly handles the concurrency using the MVCC model, which means that multiple read transactions can be done at the same time and reads can also be done while a write transaction is being committed.

Industry Compliances and Realm

While there is no official documentation on the Industrial compliances and Realm compatibility, but their encryption technology has been used by many banks in their consumer-facing applications.

For SOX and GLBA compliances, Realm has been considered secure enough to use.

Supported Datatypes and file format in Realm

Realm supports the following property types: Bool, Int, Int8, Int16, Int32, Int64, Double, Float, String, Date, and Data.

When you consider images or videos, you can’t directly store images or videos to your local Realm database. You have to either convert the files into NSDATA to store locally or just store on the server-side and define a path for it.

Realm Database Pricing

Realm Database is 100% open source, and free. But, when you buy their platform to build React Native applications, then it will cost you $1750 per month. They also have an edition which comes with Realm Studio, and tons of other development features for Enterprises.

Core Data for React Native

Many developers often misunderstand Core Data and run into frustrations of a regular database. Core Data is not a full-scale database, rather, it is a framework to manage object graphs.

An object graph is nothing but a collection of relational objects that are interconnected.

Core Data heavily relies on non-relational databases to store the objects. In React Native, where you are building a hybrid application, you can either use SQLite, or CouchDB for storage and then use Core Data to play with the object graphs.

With all being said, Core Data is capable of managing complex object graphs for apps with thousands( or even million users). But, it’s equally important to understand how Core Data differ from a regular database and when can you use it.

Core-data-vs-regular-database

Security and Core Data

It should be clear that Core Data is not a storage, and whatever data you store including passwords should be stored in keychain of the device. It’s highly vulnerable If you are storing anything in Core Data cache memory.

Apple has clearly mentioned in their Core Data programming guide that:

Core Data makes no guarantees regarding the security of persistent stores from untrusted sources and cannot detect whether files have been maliciously modified. The SQLite store offers slightly better security than the XML and binary stores, but it should not be considered inherently secure.

Concerned about securing your SQLite or CouchDB data, read their respective security practices.

Apple’s Core Data Pricing

Core Data is not open source, but it comes free with Apple’s developer license program to develop Offline first applications.

PouchDB based on CouchDB for React Native

PouchDB is an open source Javascript Database, which stores data in a JSON format and allows you to: create, read, update, delete and query your objects with a simple JavaScript API. The API can be accessed with a single call on React Native platform, which is also based on Javascript.

PouchDB was built using CouchDB protocols and storage mechanism, and that’s why CouchDB is the most reliable server-side database to pair with PouchDB. Aside from CouchDB, CouchDB is also compatible with MongoDB, MySQL, and PostgreSQL server-side databases.

PouchDB, a DB that Sync with multiple platforms easily

Similar to Firebase, PouchDB data can also be synchronized between multiple, so users can access their data on the go. Although, If you’re using any Native library, then OS specific data can’t be synced between multiple clients.

Peer to Peer Replication in a single stroke

PouchDB with its replication feature allows local storage to be disconnected from the server side while both copies can be updated concurrently. Once it’s updated, the data gets synced across multiple clients without any data leakage.

Evernote does it perfectly and lets users update their notes and they sync it back to the main database.

Securing your Local Data in PouchDB

Securing your app’s local data is difficult, but securing your local PouchDB data is relatively easy than most of the open source databases. CouchDB has an inbuilt authentication framework for React Native and it offers some amazing security features:

  • Stores the password in the hash form using PBKDF2 cryptography, which is a standard key derivation function to protect encrypted keys from brute force attacks.
  • It does stores cookies from the app, but keep refreshing every 10 minutes, which reduces possible attacks on the cookie.
  • It supports SSL, so you can easily encrypt your local data with an AES256 level of encryption.

CouchDB best practices for security would be to define proper access control rules, don’t store passwords in memory, encrypt everything using SSL and your application will be safe.

Supported Datatypes and File forms in PouchDB

PouchDB supports most of the universal data types including Boolean values, numeric values, string values, arrays, objects, and NULL.

In terms of storing document, images, videos and other files, PouchDB shines compare to other local databases.  They allow you to convert the files into either in a  base64-encoded format or as a Blob and directly store in the local memory.

If you are dealing with large files or multiple files for each user, it’s better to send them to server-side and define a path in the local Database.

PouchDB Pricing

PouchDB development and updates are publicly available on Github and it’s free to use.

Async Storage for React Native

Async storage is a local storage system, which gives you the ability to store locally and persist the data between app reboots. It comes in-built with React Native, so you can use it without any additional deployment. The downsides are slow to runtime and have no indexing capabilities.

All objects stored in Async Storage are considered as strings, all value must be serialized before storing, and deserialized after retrieving. That explains its slow runtime and no indexing capability. You should not use Async Storage while dealing with a large amount of data.

The read/write operations are quite slow compared to any other Storage systems. In terms of security, there is no encryption available locally, also the data vanishes if a user deletes the app.

Async Storage doesn’t offer any Offline Capability unless you bind it with another full-scale database like SQLite, or Realm.

Firebase for React Native

Firebase-architecture

Firebase supports a real-time NoSQL database for react-native. It can be your best bet when it comes to changes like data synchronization and offline data modification. You can suppose React Native to be as “V[view]” in MVC.

Firebase is pretty much capable of fulfilling the requirements of “M[model] and C[controller] in MVC” to react Native based applications. Since the idea behind the development of React was to provide a user interface, there was something needed to support and made it fully functional at the backend. This is where firebase as a NoSQL BaaS comes into play.

Real-time data Sync

The biggest advantage of using firebase for react-native is that real-time data is synced across all clients at a time. This is really important in the case when your app suddenly goes offline due to unavailability of an internet connection.

Moreover, when you want to develop a cross-platform app with its iOS, Android, and Javascript SDK, you will have an advantage of not caring about the constant data updates as all your clients will share a common real-time database instance.

Minimal setup

Another advantage to using react native and firebase together is that it provides a cross-platform API that requires a minimal setup while you are using it with your app. Moreover, you will not need any application server to access data as firebase real-time database can be directly accessed from a mobile device.

Offline persistence with Firebase

As mentioned above, firebase applications have the advantage to work offline (given that the application goes offline after connection established at the first time).

Also, there are following additional offline persistent capabilities that you can enable in firebase Javascript SDK:

  1. Marking user presence as offline/ online: While developing a real-time application, you will have to mark the state of a user as connected (online) and disconnected (offline or busy). This can be handled by firebase onDisconnect primitive.
  2. Timestamp when the user goes offline: Firebase real-time database also facilitates storing timestamp when a user gets disconnected every time. This timestamp can be used to identify exactly at what time the user goes offline.

The above mentioned offline capabilities of firebase make it as most suitable database while developing apps that takes user’s presence and real-time data transfer into account.

Security with Firebase

Encryption

Firebase boasts of an easily understandable data access security rule pattern. It is hosted on SSL (Secure Socket Layer) which keeps the connection safe with the client.

However, data is not encrypted at server side which makes it prone to security threats and theft. Hence, it is advisable to not use Firebase as a database for apps which needs to handle sensitive data.

You can use other local databases such as Realm or combination with any other server-side database to store your sensitive data with encryption.

However, if you somehow wish to use the same for these apps you need to make sure your data remains encrypted and also your encrypted key doesn’t remain in that database itself.

Authentication and Authorization

Firebase boasts of a simple easy-to-access API which can be used to authenticate users with data access and manipulation with some robust security rules.

You are independent to integrate firebase solely with your client-side code or your existing login server. One major advantage which goes hand-in-hand with firebase authentication is that it boasts inbuilt functionality for login authentication (via email/ password).

Moreover, you can also integrate third-party providers with your firebase.

Security rules for firebase are easy to understand and are properly defined in firebase official documentation. They are a custom set of declarative language which can be used for data validation and authorization.

Administrators can define “Read/ Write” rules using JSON structure for any sort of level in application data tree.

App performance with Firebase

Data transfer

Firebase is good to go with scalable applications where you want to transfer your data to different users at a time without having to care for any data breakage. In fact, data serving and synchronization is too fast so that you can easily transfer files to any number of users across the globe.

Moreover, with Firebase, hosting comes an add-on advantage for you. It has free CDN and SSL layer with cloud storage. This is the only area in which firebase triumphed over other local databases.

Data Querying

This is something which is not possible in firebase. Apart of some basic pagination and data filtering, you can’t expect firebase database to do anything for you.

Moreover, firebase does not come with any sort of searching capabilities so you have to rely really on your own common sense to get it done. You can always use any third party service for this purpose.

Handling Relations

Firebase as a NoSQL database is least suitable for handling relations. Since the data is mainly stored in a big JSON file. There is no specific way through which you can declare “one to many” or “many to many relationships” at all.

For instance, in some cases, you might encounter some problem to change the specific data attribute such as name in a chat app for all users. For this, you will want to change the attribute for all users or everywhere you have used it.

So, it’s not a specific way for all the users on application to change their name which is not a viable option at all.

Industry Compliances and Firebase

Firebase believed to only be compatible with SOX regulations for Financial and Banking organizations.

Supported Datatypes and file formats in Firebase

Some firebase supported data types are Boolean, bytes, date and time, integer, map, null, text string and reference.

No support for Array

Moreover, you can’t store arrays in firebase. In case, you declare an array then it will then stored by default in the form of an object along with integers as the key names.

Uploading files in firebase

One major challenge you might encounter while using Firebase as a react native database might be in uploading the files (like images for profile building concerns) as the SDK won’t work in this case.

The reason being is that in the mobile environment you can only get the file path whereas the SDK require BLOB which can be only provided by the web browser.

In this case, you might have to prefer some 3rd party libraries to address this issue. For example: react-native-file-picker and react-native-fetch-blob

Integration and Migration in Firebase

Integrators

Firebase comes with some integrators which is an obvious part as it is owned and maintained by Google. So, you don’t need to play with your code every-time as these integrations are super easy to configure and use.

Following are some of the SDK integrators that you can use with firebase:

  • OAuth authentication
  • File storage
  • Database backups
  • Automagical scaling
  • CLI for deploying and other duties
  • Free Tier

Push notifications in firebase

Apart from these integrations, firebase allows authenticating push notifications through FCM. However, configuring it in an easier way is unlikely everyone’s piece of cake.

Luckily there is one library that helps you build it easily after going through some sort of configuration process. Just start the listener wherever you want and you are good to go. Also, this library helps you send custom local notifications as well.

Migration from firebase to other databases

With Firebase, it’s hard (yet not impossible) to migrate data since data is stored as JSON. However, you can always import/ export your data from firebase in a JSON file and then you can use any other database that reads JSON data.

Firebase Pricing

Firebase is not open source, and their pricing is complex.

Firebase-pricing

SQLite for React Native

SQLite was designed to provide local data storage for mobile devices. It is a relational database management system designed to meet the storage demands of mobile applications. The word “lite” in SQLite describes it as being a lightweight(ed) library based database which requires minimal setup. SQLite can be integrated with the mobile application to directly access the database.

SQLite can be described as an ACID compliant database that implements most of SQL based standards although with some significant omissions. The architecture of SQLite is file-based with some tools which can handle all types of data with ease and simplicity.

Offline persistence with SQLite

To enable offline persistence with SQLite, you can use a react-native-SQLite-storage plugin to manage the data within the app. When a file is generated when you need to instruct from SQLite to open the file that is saved in the documents folder. You can do this by modifying your openDatabase call mentioned in step 6 of this link.

Security with SQLite

Data Encryption

SQLite does support data encryption with an extension named as SQLite Encryption Extension (SEE) which is provided on their official website. However, the extension is licensed which means you have to pay the one-time fee to use it.

The extension SEE allows SQLite to read/ write data in an encrypted manner such that data remains inaccessible to outsiders. SEE is built with various algorithms that implement encryption and makes it work for it.

Encryption algorithms such as RC4 with security enhancements, AES-128 in OFB mode, AES-128 in CCM mode and AES-256 in OFB mode are used respectively for each of the seven variants. However, the seventh variant supports all algorithms.

Apart from SEE, there are several others implementations with which you can encrypt your data in SQLite :

  • WxSQLite – wxSQLite is a C++ wrapper which can be used to encrypt SQLite data.
  • SQLCipher – SQLCipher is an open source extension that supports 256 bits AES encryption. It uses OpenSSL’s libcrypto to implement encryption.
  • SQLiteCrypt – It supports API based encryption. It requires custom implementation though.

App performance with SQLite

Query Performance

Often, query performance with SQLite is a matter of discussion among developers. There is a common notion among every developer that SQLite is not better in terms of query performance and speed. However, it is not so. SQLite can be used to query perform at an extreme level.

One of the easiest ways to optimize performance in SQLite is to make the disk access less often. But, to make it happen you must be familiar with the overall understanding of SQLite information processing. You must determine and measure the process where SQLite is consuming more time.

Moreover, while performing basic operations such as insert/ update/ delete in SQLite, you can use the correct set of Begin and End operators so that every time when a transaction initiates, a single DML code gets executed and ends after the completion of modifications.

This approach is simpler and more convenient to use while query performing any SQLite transaction.

Another approach to increasing performance in case of SQLite can be to configure several parameters of DBMS using PRAGMA.

Supported Datatypes and file formats in SQLite

Some of the supported datatypes in SQLite are NULL, INT, REAL, TEXT, and BLOB.

SQLite Database Pricing

SQLite is in public domain, open source and free to use. But, if your organization wants to obtain a license for copyright infringement, then they can pay a one time fee of $6000.

Server/Side Databases for React Native App Development

MongoDB For React Native

MongoDB is an open source, a server-side database that has been built for scalability and complex applications. MongoDB follows a combined approach of using key-value stores and a relational database to store objects in JSON documents with dynamic schemas.

If you’re dealing with a large amount of data, it allows you to modify the schemas without affecting the React Native application runtime.

Rather than domain-specific languages like SQL, MongoDB uses a simple JavaScript interface for a query. This makes looking up a document as simple as passing a JavaScript object that partially describes the search target and returns the value.

MongoDB Security and Industry Compliances

MongoDB uses SCRAM-SHA-1 mechanism for authentication and a role-based access control to prevent unauthorized infiltration to server-side data.

To abide with Industry compliances, MongoDB offers  Kerberos and LDAP proxies to protect consumer’s data.

With that being said, MongoDB security practices have adhered to these following compliances:

  • HIPAA in Healthcare industry
  • SOX in Information technology and Banking organizations.
  • GLBA(Gramm Leach Bliley Act) for consumer data protection in Financial Corporations.

MongoDB compatibility with React Native

MongoDB offers a rich ecosystem of cross-platform libraries to build scalable applications with React Native. MongoDB is a document based database, which can read and write JavaScript objects communicating smoothly between the server and app.

MongoDB as a server-side is compatible with these local databases:

  • Realm
  • SQLite
  • Async Storage combined with Core Data or SQLite
  • PouchDB

React Native app performance and scalability with MongoDB

MongoDB was built with scalability and high performance in mind. Organizations like Baidu and Adobe use MongoDB to store and process data from millions of users. According to their official documentation and case studies, the performance can be scaled to:

  • 100k+ database read and writes per second without interrupting the standard latency SLAs
  • It can store 1 Billion + documents in their database

I believe these metrics would be enough for 95% of the startup and enterprise building their apps with React Native.

MySQL for React Native

MySQL is a relational database that is based on SQL. MySQL is released as an open source license and is developed, distributed and supported by Oracle distributions.

MySQL Performance in React Native applications

MySQL supports thread-based memory allocation which makes it more fast and reliable. Operations such as joins execute faster in MySQL.

Moreover, MySQL does not perform memory allocation after query initialization which is necessary for a better query performance.

MySQL Security in React Native

MySQL is made secure with a password-based encryption system that implements several data layers for security. The verification is host-based which makes it more flexible.

It also supports encryption which makes it more secure from the server-side vulnerabilities.

Scalability and Limits

MySQL is designed to store larger data. There are some cases where it has been easily reported to store about 50 million records. MySQL has the capability to support up to 64 indexes per table.

Each index of the table may incorporate about 1 to 16 columns. Index of InnoDB tables can be wider as either 767 bytes or 3072 bytes whereas MyISAM tables have an index width of about 1000 bytes.

MySQL compatibility with React Native Local Database

If you want to store data locally on the mobile device then you can use AsyncStorage for React Native.

There are few libraries that will allow you to use SQLite with React Native and MySQL. Also, realm works in a great way with MySQL when you are working on Android.

MySQL Compliances

As mentioned above, MySQL can be used to store larger data. So, if you are on a hunt for the server side database which can serve large chunks of data across server, it must be your best bet in that case.

Banking organizations have been using MySQL for their applications, so it’s safe to assume MySQL comply with Banking regulations.

 

Amazon DynamoDB For React Native

Amazon DynamoDB was designed and developed as a fully-fledged and managed NoSQL database service which runs on the AWS cloud.

DynamoDB is made completely decentralized with minimal administration needs. It is cost effective database with horizontal scaling, so you need to only pay for the storage and your IO throughput while using DynamoDB.

Performance in DynamoDB

DynamoDB is performance optimized as it automatically made the data transfer on tables easier over multiple tables.

While using DynamoDB, you don’t need to take care of scaling and operating of a distributed database. Moreover, complex functionalities of a distributed database such as initial setup, configuration, cluster scaling, replication etc. are managed by Amazon.

You only need to use the API provided, else rest is taken care of.

Security in DynamoDB

With DynamoDB, encryption is easier. When it comes to server-side encryption, data is transferred by the user in an unencrypted form on the server where it will be then encrypted after uploading. Amazon KMS can be used to manage keys.

DynamoDB compatibility with React Native and other Local Databases

For react native, you can use react-native-DynamoDB wrapper by npm. Also, on Github, AWS SDK for React Native Developer preview includes support for S3, DynamoDB, Lambda, and SNS. This starter automatically provisions a Serverless infrastructure with authentication, authorization, image storage, API access, and database operations. It also includes user registration and MFA support.

DynamoDB with Realm: If your app requires running complex queries from the client end then Realm can be your best choice. Moreover, in such case, you can handle the backend purpose with DynamoDB.

Conclusion

When you look at a suitable database for your react native application, you need to know about your requirements in the first place. Realm as local database works well in every possible requirement where SQLite and Core Data fail to the same level of performance, security, and scalability.

For example, Realm performs best in case of data querying. In Fact, it is 3x faster than SQLite in this case.

Firebase is well suited in situations where you want to develop real-time applications. For example, an instant messenger based app where you want to showcase whether any user has read the message or not.

But, It’s a million dollar idea, then you should better choose Realm or SQLite.

SQLite is suitable in such cases where you don’t need to access “real” database but still, you want the capabilities and power of a relational database.

In the case of Server-Side databases

Organizations with a small database and looking for a more generic solution often choose MySQL and other full-scale databases. MySQL lacks speed and developers face difficulties with large volume data and their undefined schemas.

MySQL is widely used for its performance, flexibility, reliable data protection and high availability case.

But, when your data is unstructured and complex or when you can’t accurately define your schemas, MongoDB would be the better choice. MongoDB will meet all your challenges with their document-based data modeling.

Opting out for DynamoDB might be a tedious task in terms of scalability. Though DynamoDB can be used at a lower scale it’s often a matter of challenge with a large amount of data.

However, if you are looking for a backend based database to store JSON documents, DynamoDB might be useful in this case.

If you have any questions or thoughts, let us know in the comment section.

Purvak Pathak

When it comes to mobile applications, few have the rare attention to detail like Purvak. He frequently shares his thoughts about building mobile applications on Linkedin.

  • Amazing article! Thanks. I`m in a certain situation and need some help. I`m developing an application using React Native. Which one would be the best database option to choose in the given scenario:

    – The app must work offline (actually, will be used by people that almost 90% of the time will not have internet access);
    – The app must download some initial data from the database server (mysql) using an already existing API;
    – The user will have to manually sincronize everything created in the application through a menu (“Sincronize data”). This menu will get the data from the app and send to the database server. This step is just as it is: send the data from the mobile application database to the server. There is no possible duplication of data.
    – Sometimes, the data from the server may change. Maybe there it is a new record from a table, maybe someone deleted something that the application is using.

    This is my problem and what I`m struggling with: I dont want to replicate the database schema from the server to the application database. This could give me more problem as the schema from the server database changes. How could I possible handle this?

React-Native

Building World-class React Native Applications with Efficiency and Speed

Get our latest React Native development insights delivered directly to your inbox

You have Successfully Subscribed!