Spaces:
Running
title: GPU Capacity
emoji: π°οΈ
colorFrom: green
colorTo: red
sdk: docker
app_port: 7860
pinned: false
hf_oauth: true
hf_oauth_scopes:
- email
hf_oauth_authorized_org: huggingface
gpu-capacity
Near real-time AWS GPU on-demand capacity checker. Answers "where can I spawn a G5 right now?" by probing real capacity: it creates a 1-instance targeted On-Demand Capacity Reservation in each AZ and cancels it immediately. Success means the capacity actually exists β unlike spot placement scores or instance type offerings, which are proxies.
Usage
AWS_PROFILE=<profile> uv run gpu-capacity
# then open http://127.0.0.1:8300
One representative (smallest) size per GPU family is swept automatically when
AUTO_REFRESH_MINUTES is set (the deployed Space uses 15); any other size can
be probed on demand from the dashboard input or the API. Results are cached in
state.json and shown with their age; they fade once older than
STALE_AFTER_SECONDS (default 900).
On the Space, STATE_FILE lives in the mounted HF bucket
(rtrm/gpu-capacity-storage on /data), so results survive restarts β and if
the restored state is fresher than the refresh period, the startup sweep is
skipped entirely.
API
GET /api/availability/{instance_type}β cached availability for one type (?refresh=trueprobes synchronously first,?region=eu-west-1narrows)GET /api/stateβ full cached grid (types Γ regions, per-AZ detail)POST /api/probeβ{"instance_type": "g5.12xlarge", "region": "eu-west-1"}(regionoptional β sweeps all configured regions; any type accepted)
Reading is public. Probing (POST /api/probe, refresh=true) requires a
"Sign in with HF" session and is restricted to Hugging Face org members
(hf_oauth_authorized_org gates the sign-in; the backend re-checks org
membership / a verified @huggingface.co email). Sign in from the direct URL
(https://rtrm-gpu-capacity.hf.space) β session cookies don't work inside the
hf.co iframe.
Config
Types and regions: gpu_capacity/config.py. Env vars: AUTO_REFRESH_MINUTES
(background sweep, default 0 = off), STALE_AFTER_SECONDS, HOST, PORT,
STATE_FILE. AWS credentials come from the default boto3 chain
(AWS_PROFILE locally, AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY secrets on
the Space).
Cost & safety
- Reservations are billed per second at the on-demand rate; a probe lives
~1β3 s, so a full 8-region sweep for one type costs well under $0.01
(except p4d/p5 which are usually not ODCR-able anyway β they show up as
unsupported, i.e. Capacity Blocks territory). - Only immediate reservations are created (no
StartDate/CommitmentDuration), which are free to cancel at any time. Future-dated reservations and Capacity Blocks β the ones with commitments β go through different parameters/APIs and cannot be triggered accidentally. - Every probe reservation gets
EndDate = now + 30 min(auto-expires if the service dies between create and cancel), apurpose=capacity-probetag, and a startup sweep cancels any leaked tagged reservation.
Reading the grid
| status | meaning |
|---|---|
available (n/m AZ) |
reservation succeeded in n of m offered AZs |
no capacity |
AWS returned InsufficientInstanceCapacity everywhere |
quota / denied |
account quota or IAM/SCP blocks the check (not a capacity signal) |
n/s |
type not reservable via ODCR there (p5 β Capacity Blocks) |
β |
type not offered in that region |
Note: results are account-specific (quotas, SCPs), which is what you want β "can this account get a G5 there".
Latency: an available answer comes back in ~1 s per region; a no capacity
answer takes 10β20 s because EC2 genuinely attempts placement before returning
InsufficientInstanceCapacity. Probe creates run with retries disabled β
botocore would otherwise retry that error (HTTP 500) with backoff and multiply
the wait.
IAM
ec2:CreateCapacityReservation, ec2:CancelCapacityReservation,
ec2:DescribeCapacityReservations, ec2:DescribeInstanceTypeOfferings,
ec2:CreateTags (on capacity reservations).