Skip to content

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 clone into a new folder, new venv, pip install -r requirements.txt). If that fails, the deploy will too.

3. Streamlit Community Cloud

  1. Go to share.streamlit.io and sign in with GitHub.
  2. Create app → pick the repository, branch and main file (app.py).
  3. Advanced settings → Secrets: paste your keys in TOML format:

    OPENAI_API_KEY = "sk-..."
    
  4. 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.

  1. On huggingface.co → New Space → SDK: Docker → hardware: CPU basic (free).
  2. Add the Space as a second Git remote and push:

    git remote add space https://huggingface.co/spaces/<your-name>/<space-name>
    git push space main
    
  3. In the Space's Settings → Variables and secrets, add OPENAI_API_KEY as a secret.

  4. Make sure the Dockerfile serves on 7860, and add this to the top of the Space's README.md:

    ---
    title: My RAG Demo
    sdk: docker
    app_port: 7860
    ---
    

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)

  1. render.com → New → Web Service → connect your GitHub repository.
  2. Settings:

    Field Value
    Runtime Python (or Docker, if you have a Dockerfile)
    Build command pip install -r requirements.txt
    Start command uvicorn app.main:app --host 0.0.0.0 --port $PORT
    Instance type Free
  3. Environment → add OPENAI_API_KEY and any other variables.

  4. 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):

Procfile
web: uvicorn app.main:app --host 0.0.0.0 --port $PORT

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_tokens and input length (reject 50-page pastes).
  • Add simple rate limiting per IP or session (for example slowapi for FastAPI, or a counter in st.session_state for 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_tokens and rate limiting are in place.
  • The live link is at the top of your README.

Next: Turn a project into a portfolio-ready GitHub repo →