Deploy your AI app for free¶
Beginner · 20 min · needs a GitHub account
A project with a live link is worth far more in an interview than a GitHub repo nobody runs. This tutorial gets your app online with a public URL. Every platform here deploys straight from a GitHub repository, so push your code first (see Use Git every day).
Free tiers change
Limits and prices below were accurate in late 2026 but change often. Check each platform's pricing page before relying on it, and never put a credit card on a platform without setting a spending limit.
1. Pick a platform¶
| Your app | Easiest free option | Notes |
|---|---|---|
| Streamlit app | Streamlit Community Cloud | Free, deploys from GitHub in minutes; app sleeps after inactivity |
| Streamlit or Gradio demo, ML-flavoured | Hugging Face Spaces | Free CPU tier; great visibility in the AI community |
| FastAPI backend | Render (free web service) | Spins down after ~15 minutes idle; first request then takes ~1 minute |
| Anything with a Dockerfile | Hugging Face Spaces (Docker) or Render | Same image you run locally |
| App + database, always on | Railway or Render paid tiers | A few dollars a month; worth it for a portfolio centrepiece |
All of them give you HTTPS and a URL like your-app.streamlit.app or your-app.onrender.com.
2. Before any deploy¶
Your repository needs:
my-ai-app/
├── app.py # or app/main.py for FastAPI
├── requirements.txt # pinned versions: pip freeze > requirements.txt (then trim to what you use)
├── .gitignore # includes .env
└── README.md # with the live link, once you have it
- No keys in the code. Read them from the environment (see Manage API keys and settings); each platform below has a secrets page.
- No large files. Models, vector indexes and datasets don't belong in the repo: build the index at startup from a few documents, or load it from a hosted vector DB.
- Run it locally from a fresh clone (
git cloneinto a new folder, new venv,pip install -r requirements.txt). If that fails, the deploy will too.
3. Streamlit Community Cloud¶
- Go to share.streamlit.io and sign in with GitHub.
- Create app → pick the repository, branch and main file (
app.py). -
Advanced settings → Secrets: paste your keys in TOML format:
-
Deploy. A few minutes later you get
https://<your-app>.streamlit.app.
Read the key with st.secrets["OPENAI_API_KEY"]. Top-level secrets are also set as environment variables, so
os.getenv("OPENAI_API_KEY") works too. Every git push redeploys automatically. Pin your Python version in the
app's settings to match what you use locally.
4. Hugging Face Spaces (Docker)¶
Spaces run a Docker image, so the Dockerfile from the Docker tutorial works with one change: Spaces expect the app on port 7860.
- On huggingface.co → New Space → SDK: Docker → hardware: CPU basic (free).
-
Add the Space as a second Git remote and push:
-
In the Space's Settings → Variables and secrets, add
OPENAI_API_KEYas a secret. -
Make sure the Dockerfile serves on 7860, and add this to the top of the Space's
README.md:
For a Streamlit app the last Dockerfile line becomes
CMD ["streamlit", "run", "app.py", "--server.address=0.0.0.0", "--server.port=7860"].
Gradio apps can use the gradio SDK directly without a Dockerfile.
5. Render (FastAPI)¶
- render.com → New → Web Service → connect your GitHub repository.
-
Settings:
Field Value Runtime Python (or Docker, if you have a Dockerfile) Build command pip install -r requirements.txtStart command uvicorn app.main:app --host 0.0.0.0 --port $PORTInstance type Free -
Environment → add
OPENAI_API_KEYand any other variables. - Create Web Service. Your API is at
https://<name>.onrender.com/docs.
Note --port $PORT: platforms tell your app which port to use through the PORT environment variable. Hard-coding
8000 is the most common reason a deploy "succeeds" but never responds. On the free tier the service sleeps when
idle, so the first request after a while is slow; that's fine for a portfolio, not for a product.
6. Railway¶
Railway deploys from GitHub with almost no configuration and makes adding Postgres one click. It uses usage-based
pricing with trial credits rather than a permanent free tier. Add a Procfile (or a Dockerfile, which takes
priority):
New Project → Deploy from GitHub repo, add variables in the Variables tab, then Settings → Networking → Generate Domain for a public URL.
7. Once it's public: protect your key¶
A public LLM app is a public way to spend your money. Before sharing the link:
- Set a monthly spending limit on the API provider account.
- Cap
max_tokensand input length (reject 50-page pastes). - Add simple rate limiting per IP or session (for example
slowapifor FastAPI, or a counter inst.session_statefor Streamlit). - Use a cheap model for the demo.
- Optionally gate it behind a password or "bring your own API key" field.
- Watch the provider's usage page for the first few days.
Troubleshooting¶
| Symptom | Fix |
|---|---|
| Build fails on a package | Pin versions; remove packages you don't use; check the Python version matches |
| Deploy succeeds, URL never loads | Listen on 0.0.0.0 and $PORT (7860 on Spaces) |
AuthenticationError |
Secret not set, or set under a different name than the code reads |
| Out of memory | Don't load big local models or sentence-transformers on free tiers; call hosted APIs instead |
| Works once, then data disappears | Free tiers have no persistent disk: store data in a hosted database |
Checklist¶
- App runs from a fresh clone with pinned requirements.
- Keys are platform secrets, not in the repo.
- The app listens on the platform's port.
- Spending limit,
max_tokensand rate limiting are in place. - The live link is at the top of your README.