1. SQLite Is Ready for Production

Many tutorials say SQLite is only for testing. For most small and medium web apps, that advice is wrong. The SQLite team says SQLite works well for sites with up to about 100,000 visits a day, and they call that number cautious.

SQLite runs inside your Python process. PostgreSQL and MySQL run as separate servers, so every query travels over a network connection. SQLite skips that trip and reads straight from a file on the same disk. Simple queries often finish in well under a millisecond.

SQLite also has no server to install, patch or pay for. Your whole database is one file that you can copy, back up and open on your laptop.

2. Why Your Data Disappears on Some Hosts

SQLite rarely fails in the cloud because of speed. It fails because of the disk.

Many hosts give each app a temporary disk. Heroku is the best-known example. Each deploy or restart builds the app from scratch and throws the old disk away. A SQLite file next to your code goes with it. People then blame SQLite, but the host deleted the data.

The fix is simple. Keep the database file in a folder that the host promises to keep.

3. Turn On WAL Mode

By default, SQLite locks the whole file while it writes. Readers wait until the write finishes. On a busy site, those waits add up.

Write-Ahead Logging, or WAL mode, fixes this. In WAL mode, readers do not block the writer, and the writer does not block readers. Your Gunicorn workers can all read at the same time while one of them saves new data.

SETTINGS FOR EACH NEW CONNECTION

Run these commands each time your app opens a database connection.

PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA busy_timeout = 5000;
PRAGMA foreign_keys = ON;

The busy_timeout line tells SQLite to wait up to five seconds for a lock instead of failing at once. It removes most "database is locked" errors during traffic spikes. The synchronous = NORMAL line speeds up writes and stays safe in WAL mode.

4. Set Up Flask and Django

Flask with SQLAlchemy

Point your connection string at the data folder. Read the folder path from an environment variable, so the same code runs on your laptop and on your host.

import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
data_dir = os.environ.get("APP_DATA_DIR", "/app/data")
os.makedirs(data_dir, exist_ok=True)

app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{os.path.join(data_dir, 'app.db')}"
app.config["SQLALCHEMY_ENGINE_OPTIONS"] = {
    "connect_args": {"timeout": 15}
}
db = SQLAlchemy(app)

Django settings.py

Change the NAME of your default database so the file lives in the data folder.

import os
from pathlib import Path

DATA_DIR = Path(os.environ.get("APP_DATA_DIR", "/app/data"))
DATA_DIR.mkdir(parents=True, exist_ok=True)

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": DATA_DIR / "db.sqlite3",
        "OPTIONS": {
            "timeout": 20,
        },
    }
}

Django 5.1 and later also accept an "init_command" option, so you can turn on WAL mode right in these settings.

5. The One-Server Rule

SQLite has one firm limit. Only one server should open the database file.

One server can run many Gunicorn or Uvicorn workers, and they share the file safely. Two servers that share one SQLite file over a network drive can corrupt it. If your app needs several servers behind a load balancer, or servers in different regions, move to PostgreSQL.

Most apps never reach that point. One server with a few workers handles far more traffic than most side projects and small businesses see.

6. SQLite on Cloudilio

Cloudilio gives every app a data folder at /app/data. Your app also finds the path in the APP_DATA_DIR environment variable.

  • Your data stays put. Files in /app/data survive new versions, restarts and rollbacks.
  • Daily backups. Cloudilio backs up the folder every day. You can restore any backup with one click or download it as a .tar.gz file.
  • See your data. The Data & backups page lists your saved files. Open a SQLite database there to browse its tables without writing a query.

The storage guide walks through backups and restores step by step.

Cloudilio Engineering Team
Database Systems Group • Cloudilio

Cloudilio hosts Python apps. You publish Flask, Django, FastAPI, Streamlit and plain Python scripts without managing a server, and your app's data stays safe between updates.