,

Hugging Face Spaces and Gradio: Great for Demos, Wrong for Production (Hugging Face Series, Part 14)

A Hugging Face Space turns a model into a shareable Gradio demo in three files. Here is how a Space runs, a worked example, and the hard line where a demo must graduate to real serving.

Hugging Face Series · Part 14 of 17

TL;DR

A Hugging Face Space is a managed app-hosting tier built on a git repo. You push app.py, a requirements.txt and a README.md with a YAML block, and the platform builds a container and serves it at a URL. Three SDKs exist: gradio, docker and static. Gradio is the fastest path to a working demo.

Treat a Space as a demo and review environment, not production. Free CPU Spaces sleep on idle, share a multi-tenant box, carry no SLA, and run your code in a place you do not control. The moment a demo needs uptime, private data, access control or a stable address, move it to Inference Endpoints, a TGI container, or your own GPUs.

Who this is for: The infrastructure admin or platform engineer who already runs internal demo boxes, staging clusters and PaaS app tiers, and now needs to know where Hugging Face Spaces fit. If you have ever drawn the line between a developer-run sandbox and a service your team is paged for, you already have the mental model this part needs. Prerequisites: you can read a Python file and a YAML block, and you have a free Hugging Face account.

Someone on the data team sends you a link to a model demo and says it is broken. You open it and wait fifteen seconds while a grey screen says the Space is starting. Then it loads fine. Nothing is broken. The free Space went to sleep after a stretch of no traffic, and the first request had to wake it up. That single behavior tells you almost everything about what a Space is and is not. It is a convenient place to put a demo. It is not a place to put a service that someone expects to answer instantly, every time, with data you cannot afford to leak.

Spaces are the part of Hugging Face that finally makes a model visible to people who do not live in a terminal. That is genuinely useful. It is also where infra teams get into trouble, because a demo that works in a meeting quietly becomes the thing a department depends on, and nobody upgraded it to deserve that trust. This part covers how a Space runs, how to ship a Gradio one, and the line where a Space becomes the wrong tool.

Tested on: Python 3.11+, the gradio SDK. These are the versions this walkthrough was checked against in mid-2026. The Hugging Face stack moves quickly, so pin the version you install rather than pulling latest, and expect a major release to shift some defaults.

What a Space is

Strip away the friendly framing and a Space is a managed platform-as-a-service tier sitting on top of a Hub git repository. The repo holds your code and config. When you push a commit, the platform reads the YAML block at the top of README.md, builds an image, installs your dependencies, starts a container, and exposes it behind a URL and an iframe. If you run an internal Heroku-style app tier or a managed container service, this is the same shape: git push in, running container out, with the build and the reverse proxy handled for you.

The config lives in the README.md YAML header, not in a separate manifest. Keys like sdk, sdk_version, app_file, app_port and python_version control the runtime. The default Python version is 3.10, and for a Docker Space the default exposed port is 7860. That is the whole control plane for a basic Space: a few lines of YAML and a file the platform knows how to run.

How a Space runsGit repoapp.pyrequirements.txtREADME.md (YAML)Buildinstall depsContaineryour app runsURLiframe
A Space is a git repo the platform builds into a container and serves. The YAML in README.md is the control plane.

This is the same registry-plus-runtime idea you have seen before in this series. The Hub stores models the way a container registry stores images, a point covered in the Harbor for Beginners guide. A Space adds the part a registry does not: it runs the thing. That convenience is the whole appeal, and also the whole risk.

Three SDKs, and why Gradio wins for demos

The sdk key accepts three values: gradio, docker and static. Each is a different amount of control traded against a different amount of work. The old built-in Streamlit SDK is gone as a first-class option; if you want Streamlit now, you select the Docker SDK and use the Streamlit template. That change matters for planning, because it means anything beyond a Gradio or static app is a container you own end to end.

SDKWhat you writeControlBest for
gradioapp.py plus requirements.txtLow; platform owns the serverModel demos, quick UIs, internal review
dockerA Dockerfile and your full stackHigh; you own the image and portFastAPI, custom servers, Streamlit, special deps
staticHTML and JavaScriptNone server-sideFront ends that call an API elsewhere

Gradio wins for demos because it removes the server entirely. You write a Python function and describe its inputs and outputs, and Gradio builds the web UI, the request handling and the API for you. For an infra reader the trade is clear: you give up control of the web layer in exchange for not building one. That is the right trade for a demo and the wrong trade for a service you have to operate, which is exactly the line this part is about.

Shipping a Gradio Space, end to end

A working Gradio Space is three files. Here is the application file. It loads a small image-classification model through a transformers pipeline, the same pattern from earlier in this series, and wraps it in a Gradio interface.

# app.py
import gradio as gr
from transformers import pipeline

clf = pipeline(task="image-classification",
               model="julien-c/hotdog-not-hotdog")

def predict(img):
    preds = clf(img)
    return {p["label"]: p["score"] for p in preds}

app = gr.Interface(
    predict,
    inputs=gr.Image(type="pil"),
    outputs=gr.Label(num_top_classes=2),
    title="Hot Dog or Not",
)

if __name__ == "__main__":
    app.launch()

The second file lists dependencies. The Spaces runtime installs these at build time.

# requirements.txt
transformers
torch

The third file is the YAML config at the top of README.md. This is what tells the platform it is a Gradio Space and which file to run.

# README.md (YAML header)
---
title: Hot Dog Or Not
emoji: 🥩
colorFrom: red
colorTo: yellow
sdk: gradio
app_file: app.py
pinned: false
---

Worked example

Push those three files to a new Space repo. The build log shows pip installing transformers and torch, then the App tab renders an upload box. Drop in a photo and you get back two labels with scores, for example hot dog 0.98 and not hot dog 0.02. First load on free CPU takes several seconds because the model has to download and warm.

The common failure: the build finishes but the App tab shows a runtime error. Almost always it is a missing line in requirements.txt (the import works on your laptop because the package is already there, but the clean build box has nothing). Read the build and container logs in the Space, add the missing dependency, push again. The second build is the fix, not a restart.

Read the build log like a deploy

The part that trips up first-timers is treating a Space like a script instead of a deploy. It is a deploy. Every push triggers a build, the build has a log, and the running container has its own log, both visible in the Space UI. When something is wrong the answer is in one of those two places, the same way you would check a CI build log and then the container logs on any platform you run. Pin sdk_version in the YAML once a demo matters, because leaving it unset means a future build can pull a newer Gradio and change behavior under you, the classic floating-tag problem you already avoid with container images. Pin the version, read the logs, and a Space behaves like any other small deployment target rather than a black box.

What happens on a requestBrowserupload imageGradioroutes callpredict()your codeModelin VRAMThe response returns back along the same path. One process, one box, one tenant at a time.
Gradio owns the web layer so you only write predict(). That is the whole convenience, and the whole limit.

Hardware, sleep, and the bill

Every Space starts on the free CPU Basic tier, which is a shared 2 vCPU box with 16 GB of RAM. That runs a small model demo fine. For anything that needs a GPU you upgrade the Space to a hardware flavor, and the platform swaps the underlying machine. The flavors run from a single T4 up through L4, L40S and A100 configurations, including multi-GPU options like a100x4 and l40sx8. There is also ZeroGPU, a free shared pool of H200-class GPUs that is allotted by quota rather than dedicated to your Space, which is meant for demos that need a GPU only in short bursts.

TierRoughly what it isBillingSleeps on idle
CPU Basic2 vCPU, 16 GB, sharedFreeYes
ZeroGPUShared H200 pool, quota basedFree, metered by quotaYes
GPU upgradeT4 up to multi-A100Per hour while runningOptional

Two behaviors decide whether a Space is safe to depend on. The first is sleep. Free tiers pause after a period of no traffic, and the next request pays the wake-up cost, which is the grey screen from the opening story. The second is the billing model on paid hardware: a GPU Space is charged for the time the hardware is assigned, so a Space you upgraded and forgot keeps billing whether anyone is using it or not. Neither behavior is a flaw. They are exactly what you would expect from a shared demo platform. They are also exactly why a Space is the wrong home for a service.

What this means if you run the platform: A Space is multi-tenant infrastructure you do not own, with no SLA, that sleeps on idle and bills GPUs by the wall-clock hour. So treat it like a developer sandbox, not production. Put secrets in the Space settings as repository secrets, never in app.py or the repo, since the code is often public. Keep regulated or customer data off it, because the data leaves your boundary the moment a user uploads it. Set a budget alert on any GPU Space, and audit for upgraded Spaces nobody is watching, the cloud-bill equivalent of a forgotten always-on instance. If a Space starts getting real traffic, that is your signal to graduate it, not to upgrade it.

When a Space is the wrong tool

The decision is not Space versus no Space. It is demo versus service, and a Space only belongs on one side of that line. The test I use is four questions. Does it need to answer instantly every time? Does it handle private or regulated data? Does it need access control beyond a public or simply-gated page? Does it need a stable address other systems depend on? One yes means a Space is the wrong tool.

Space or graduate?Needs uptime, privatedata, RBAC or a stable URL?NoYesUse a Spacedemo, review, sharingGraduate itEndpoints, TGI, your GPUsSLA, access control, stable address, owned hardware
One yes on the top question and the Space has outgrown its job.

Where to graduate to is a question this series already answers. For a managed but production-grade endpoint without running the box yourself, Inference Endpoints is the path, weighed against the other options in Part 11 on Inference Providers, Endpoints and self-hosting. For a serving container you scale and monitor yourself, Text Generation Inference is covered in Part 12 on TGI in production. For your own GPUs on the NVIDIA stack, cross over to the NVIDIA AI guide, and for an on-prem VMware build see the Private AI guide. A Space is the front porch. None of those are.

Gotcha: A Space can be called as an API, not just a UI, which is how a demo quietly becomes a dependency. Someone wires a script to the Space URL because it was there, and now an unmonitored free demo that sleeps on idle is in a real workflow. If you find this, do not patch around the sleep behavior. Stand up a real endpoint and repoint the caller. The Space was never the contract.
Note: Hardware flavors, free-tier limits and GPU pricing change. Confirm the current flavors and rates on the Spaces GPU and pricing pages before you commit a budget or a hardware choice, rather than trusting a number you remember.

What I’d ship

Use Spaces, and reach for the Gradio SDK first. For showing a model to colleagues, gathering feedback, or putting a face on a proof of concept, nothing else gets you from a function to a shareable URL as fast, and the cost on CPU Basic is zero. I keep several Gradio Spaces around for exactly this, and I would recommend any infra team do the same. The recommendation has a hard boundary, though. Do not let a Space hold private data, do not let it become a load-bearing endpoint, and do not upgrade it to a GPU and call that production. The why-not is the same in every case: it is shared infrastructure with no SLA that sleeps on idle and bills by the hour. The thing to validate first is what your demo will carry, because the failure mode is not a Space breaking. It is a Space working well enough that someone forgets it was only ever a demo.

Try this: take one model you have been meaning to show people, wrap it in the three-file Gradio pattern above, and push it. Then write one sentence at the top of the README saying what it is not for. That sentence is the cheapest governance you will ever ship.

Hugging Face Series · Part 14 of 17
« Previous: Part 13  |  Hugging Face Guide  |  Next: Part 15

References

About The Author


Discover more from Journal of Intelligent Infrastructure – By Dr Pranay Jha

Subscribe to get the latest posts sent to your email.

Leave a Reply

Your email address will not be published. Required fields are marked *

Architect’s Toolkit

About the Author

Dr. Pranay Jha is a Cloud and AI Consultant with 18+ years of experience in hybrid cloud, virtualization, and enterprise infrastructure transformation. He specializes in VMware technologies, multi-cloud strategy, and Generative AI solutions. He holds a PhD in Computer Applications with research focused on Cloud and AI, has published multiple research papers, and has been a VMware vExpert since 2016 and a VMUG Community Leader.

Discover more from Journal of Intelligent Infrastructure - By Dr Pranay Jha

Subscribe now to keep reading and get access to the full archive.

Continue reading