# Content of Today's Lecture 1. Security 2. Deployment 3. Performance and optimization ---
[Qovery](https://www.qovery.com/) ([pricing](https://www.qovery.com/pricing), [Django](https://hub.qovery.com/guides/tutorial/quickstart-django/))
[Circumeo](https://www.circumeo.io/) ([pricing](https://www.circumeo.io/#pricing))
--- # Performance and optimization The efficiency of the application must be ensured not only in the development environment – the real world behaves differently (a large number of requests, more data in the database, etc.). First, you need to determine the characteristics of the environment and the given application: - benchmarks and profiling – e.g., [Django Debug Toolbar](https://github.com/jazzband/django-debug-toolbar/) - monitoring – e.g., number of visits and server load Then optimization of the most affected parts can begin. In the Django documentation: [Performance and optimization](https://docs.djangoproject.com/en/5.2/topics/performance/) --- ## Optimizing database access - the time it takes to process database accesses depends on the amount and type of data stored in it (if the test database is small, even inefficient queries will be processed quickly, but in practice, they will cause significant slowdowns) - processing an operation directly in the database is typically faster than equivalent code in Python, e.g., `some_objects.count()` vs `len(some_objects)` - practically all database systems use so-called [indexes](https://en.wikipedia.org/wiki/Database_index) – auxiliary data structures that enable fast searching and sorting by specified attributes (columns in a table) - primary and unique keys are automatically indexed, additional indexes can be added using [`Meta.indexes`](https://docs.djangoproject.com/en/5.2/ref/models/options/#django.db.models.Options.indexes) - details see [Database access optimization](https://docs.djangoproject.com/en/5.2/topics/db/optimization/) --- ## Optimizing by caching - Django contains a [caching framework](https://docs.djangoproject.com/en/5.2/topics/cache/), i.e., temporary storage of frequently needed data in a location with fast access - often used are Memcached and Redis programs – caching in operating memory (can also be used for caching data stored in the database) - data whose acquisition takes a very long time can be cached in the database (permanent storage, but slower access) - data with a simple structure can be efficiently cached directly in files on disk Levels of caching: - entire application (website) (`django.middleware.cache`) - individual _view_, where caching makes sense (decorator `@cache_page`) - parts of templates (tag `{% cache... %}`) - any data (using [low-level API](https://docs.djangoproject.com/en/5.2/topics/cache/#the-low-level-cache-api)) --- ## Optimizing at the HTTP level - [ConditionalGetMiddleware](https://docs.djangoproject.com/en/5.2/ref/middleware/#django.middleware.http.ConditionalGetMiddleware) – sets response headers [`ETag`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) and [`Last-Modified`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified) and checks request headers [`If-None-Match`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match) and [`If-Modified-Since`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since) (using data cached on the client side) - [GZipMiddleware](https://docs.djangoproject.com/en/5.2/ref/middleware/#django.middleware.gzip.GZipMiddleware) – compresses data in the response (can be set in most web servers, e.g., [uWSGI](https://ugu.readthedocs.io/en/latest/compress.html)) - using tools for [minimizing CSS and JavaScript](https://www.imperva.com/learn/performance/minification/) --- ## Further optimization - using ASGI instead of WSGI - using a different language and package for templates (e.g., [Jinja2](https://jinja.palletsprojects.com/en/3.1.x/)) - optimizing application code (e.g., implementing a more efficient algorithm or using a more efficient library)