Choosing Hosting for a React + Django + PostgreSQL App: A Cost and Effort Framework
- Author
- Vishal Maurya
- Published on
- Reading time
- 5 min read
Overview
You have a React frontend, a Django API and a PostgreSQL database, and you need to put it online. Hosting comparisons online usually focus on the monthly bill, but the cheapest line item often becomes the most expensive option once you count your own time, risk and growth. Prices change often, so this post gives a framework you can apply with current pricing pages instead of quoting numbers.
1. List What Your App Actually Needs
Start with requirements, not products.
- Components: static frontend, Django app server (Gunicorn or similar), PostgreSQL, maybe a worker and Redis.
- Traffic shape: steady or spiky, and how many users.
- Availability: is an hour of downtime acceptable?
- Data: how valuable is it, and how fast must you recover?
- Team: who will be on call, and how comfortable are they with Linux and Docker?
A hobby project and a paying-customer product land in different places even with identical code.
2. The Three Common Options
VPS with Docker Compose. You rent a virtual server and run Nginx or Caddy, Django, Postgres and the build output yourself. You get the most control and usually the lowest predictable resource cost per unit of CPU and memory. You also own OS patching, firewalling, backups, monitoring, TLS, deploy scripts and recovery. It is a single host unless you build more.
Platform as a Service (PaaS). You push code or a container, and the platform builds, runs, scales and terminates TLS for you, often with a managed Postgres add-on. Setup is fast and operations are light. Costs are usually higher per unit of resource, can scale with each added service, and customization is limited to what the platform offers.
Managed containers. A cloud service runs your containers without you managing servers, often paired with a managed database and a CDN for the frontend. It sits between the two: more flexibility and scaling than a PaaS, more configuration than a PaaS, and a wide set of cloud concepts to learn.
3. Compare These Dimensions
Build a simple table for your candidates and score each row.
| Dimension | What to ask | | --- | --- | | Compute | Cost of the CPU and memory your Django process needs, and the cost to add a worker | | Database | Managed or self-run? Backups, point-in-time recovery, connection limits, storage growth | | Frontend | Static hosting or CDN included, or served from your own box | | Egress and storage | Bandwidth, file uploads, media storage, and charges beyond free allowances | | Environments | Cost of a staging copy | | Scaling | What happens on a traffic spike; manual or automatic | | Operations | Who patches, monitors, rotates certificates and responds at night | | Lock-in | How hard is it to move away later |
Read each provider's current pricing page and any limits on free or entry tiers, such as sleeping services or connection caps, before relying on them.
4. Count Your Own Time
Convert operational work into hours. A VPS means time to set up the server, harden SSH, configure the firewall, set up the proxy, certificates, deploys, backups and monitoring, plus ongoing patching and incident work. A managed platform replaces much of that with a higher bill. If your time is limited or an outage is costly, paying for managed pieces, particularly the database, is often justified.
5. Treat the Database Separately
Of the whole stack, PostgreSQL is hardest to lose and hardest to recover. Even if the app runs on a cheap VPS, consider a managed database for automated backups and failover, or commit to tested backups with a documented restore. Compare database options by recovery features, not just by size.
6. A Sensible Django Setup Regardless of Host
Keep the app portable so you can change your mind later.
# settings.py
import os
import dj_database_url
DEBUG = os.environ.get("DJANGO_DEBUG", "0") == "1"
ALLOWED_HOSTS = os.environ["DJANGO_ALLOWED_HOSTS"].split(",")
DATABASES = {"default": dj_database_url.config(conn_max_age=60)}
STATIC_ROOT = os.environ.get("STATIC_ROOT", "/app/staticfiles")
Configuration from environment variables, a Dockerfile, static files built at deploy time and a health endpoint will run on any of the options above. Portability reduces the cost of choosing wrong.
7. A Practical Decision Path
- Early stage and little operations time: a PaaS with a managed database.
- Cost-sensitive, comfortable with Linux, tolerant of brief downtime: a VPS with Compose, with off-host backups.
- Growing traffic, several services, a need for scaling: managed containers or an orchestrator.
You can start simple and migrate when a real constraint appears, as long as the app is containerized and configured through the environment.
Conclusion
Choose hosting by comparing compute, database safety, operations burden, scaling and lock-in, not only the monthly figure. Keep the application portable so the first decision is not permanent.
If you want help estimating the effort of each option for your app or setting up the one you choose, I can help. Contact me.