Django has proven to be a powerful web-development tool and is helping boost productivity in writing web applications. It follows the MTV architecture — model, template, and view. View handles the API endpoints, template handles the HTML and model does the database work. Starting with Django is smooth and simple, but when your app starts growing, adding real-world business constraints then the same strategies used in the beginning aren’t that effective and efficient.
Django is a good framework, but not the best in all scenarios. Its ORM offers a great help and simplicity in abstracting database access, but this simplicity can often become a bottleneck or performance pain points.
CRUD or create, read, update and delete. These are the most frequent operations performed in any database. Depending on business requirements developers design and index their databases efficiently. Though, database-designing is a very important aspect when dealing with databases, database-access seconds by a very small difference.
Usually, small or mid size applications instead of using a third-party DB service, like AWS-RDS, Azure SQL Database, etc, prefer using their own database setup. This custom DB setup is mostly done on the same machine that has the server or on a different machine in same network, depending on the performance and workloads. Here, the db-access performance becomes important because when the app-server and database are on the same machine or in the same network, then virtually there is no network-call, rather just one process calling another process, which is really faster than any API call. But, if the database is setup in a different network or with a third-party service provider, then for every database operation a network call is required, and with every operation you perform on the DB, the access latency becomes more and more crucial. Hence, it really becomes important to not only design your database schema, but to also design the way in which you interact with the data.
Simple REST APIs may require you just to provide endpoints for CRUD operations on a resource or entity, like a book or person. Functionalities like these can be nicely handled by the Django-ORM. But in real-world user flows doing any kind of operation on DB requires a good a mount of validation or pre-processing. Handling such cases with the Django-ORM is possible but may not be efficient.
Example: Consider a use case where you have provided an API to add new books in a store table. This functionality is only accessible to a user of type manager, and the store has a limit on the number of books from each subject, and every subject has a specific pattern for book-names.
Now, when developing this API to add a new book, before adding you would need to validate the user-type, the book-name pattern and book count. If these data pieces were related you could have leveraged Django’s select_related or prefetch_related to solve it. But since they are not, you’ll have to either make multiple fetch calls OR fire a custom SQL OR use sub-queries (if possible).
This was a relatively simple example, but at CodeParva, we are developing a solution for the huge self-storage industry and having very complex user-flows which require validations and checks ranging from names to long rental histories. Getting all the technically unrelated data just to process one flow would have cost us multiple visits to the database. To solve this problem we have leveraged elasticsearch.
Image credits: towardsdatascience.com
Elasticsearch is a search engine based on the Lucene library. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents. — Wikipedia.
Using Elasticsearch we have developed a seamless framework that facilitates us querying huge amounts of data in just one network call. Related or unrelated, it just takes one network call to fetch it all. This has given us a good performance boost against the normal Django-ORM.
The above mentioned approach has proven to be very effective and beneficial in the READ operations as the ES provides us richer ways to query the data and that too with data ranking, if required.
On the other side of the coin, after every line of code that is updating the database we need to update relevant the record(s) in the ES.
Using Elasticsearch as Data-Store in Django
Elasticsearch has proven to be a great resource for our use case, but it may not be the best choice for everyone, checkout some of its pros and cons listed below.
Elasticsearch is fast & powerful. Instead of searching the text directly, it searches an index, that is based on the text. Just like using an index in a book. Retrieving pages related to a keyword by scanning the index, instead of searching every page for the word.
Additional Links: