Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@
"serverless/development/dual-mode-worker"
]
},
{
"group": "Storage",
"pages": [
"serverless/storage/modelrepo/overview",
"serverless/storage/modelrepo/security",
"serverless/storage/modelrepo/testing"
]
},
"serverless/modelrepotest",
{
"group": "Manage endpoints",
"pages": [
Expand Down
171 changes: 171 additions & 0 deletions serverless/modelrepotest.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
---

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doc seems like it has a lot of overlap with testing.mdx. Which one is the canonical document?

title: "Model Repo testing"
description: "Upload a model to Model Repo and deploy it to a Serverless endpoint."
---

<Note>
Model Repo is currently in alpha and is available on Mac and Linux only. Windows support is coming soon.
</Note>

## Why use Model Repo

Model Repo lets you upload your own models to private storage on Runpod and attach them directly to Serverless endpoints. Key benefits:

- **Faster cold starts**: Models are pre-cached on the worker host rather than downloaded at runtime.
- **No HuggingFace dependency**: Your models are stored in Runpod's infrastructure, so endpoints don't require an outbound download on every cold start.
- **Private storage**: Models are stored in your account and are not accessible to other users.

---

## Manual testing

### Prerequisites

- Your email is feature-flagged for Model Repo access.
- `jq` is installed for parsing JSON output.

### Set environment variables

Export the following before running any commands. **Make sure to set your actual API key — missing this is the most common source of auth errors later.**

```bash
export RUNPOD_API_URL="https://rest.runpod.io/v1"
export RUNPOD_GRAPHQL_URL="https://api.runpod.io/graphql"
export RUNPOD_API_KEY="your-api-key" # replace with your actual API key

export MODEL_NAME="model_name" # unique name per test run — reusing the same name uploads a new version, not a new model
export MODEL_PATH="/path/to/model" # local path to the model files you want to upload
```

<Warning>
`MODEL_NAME` must be unique for each test run. If you reuse the same name, the upload creates a new version of the existing model rather than a new model.
</Warning>

---

### Step 1: Install runpodctl

**Option A: Install via Homebrew (recommended)**

```bash
brew install runpod/runpodctl/runpodctl
```

**Option B: Build from source**

```bash
brew install go # install Go, required to build runpodctl
git clone git@github.com:runpod/runpodctl.git
cd runpodctl
make # builds the binary to ./bin/runpodctl
```

<Note>
If you build from source, the binary is at `./bin/runpodctl`. Either run it with that path, or add `./bin` to your `PATH`. The steps below use `runpodctl` — adjust accordingly.
</Note>

---

### Step 2: Upload the model

```bash
# --name: the name to register the model under in your repo
# --model-path: local path to the model files
# --create-upload: creates the upload session and transfers files
runpodctl model add \
--name "$MODEL_NAME" \
--model-path "$MODEL_PATH" \
--create-upload
```

This outputs a JSON string listing all uploaded files.

---

### Step 3: Wait for the model to be hashed

After upload, the model must be hashed by an asynchronous background process. This typically completes in a few minutes but can take up to 10–15 minutes.

Poll until the `hash` field is non-null:

```bash
runpodctl model list --name "$MODEL_NAME" | jq -r '.[0].versions[0].hash'
```

While hashing is in progress, the command returns `null`:

```
% runpodctl model list --name "$MODEL_NAME" | jq -r '.[0].versions[0].hash'
null
```

Once hashing is complete, it returns the hash value:

```
% runpodctl model list --name "$MODEL_NAME" | jq -r '.[0].versions[0].hash'
71a311bdf0ca44119ed74dbef8cf573bc89b58cbc48a10fe508f756ebb1922dc
```

---

### Step 4: Get your user ID and model hash

```bash
export USER_ID="$(runpodctl user | jq -r '.id')" # your Runpod user ID
export MODEL_HASH="$(runpodctl model list --name "$MODEL_NAME" | jq -r '.[0].versions[0].hash')" # the hash from step 3
```

---

### Step 5: Deploy a Serverless endpoint with the model attached

```bash
# --name: name for the endpoint
# --hub-id: the Hub template to deploy
# --gpu-id: GPU type
# --workers-max: maximum number of active workers
# --workers-min: minimum number of workers kept warm
# --model-reference: attaches your model to the endpoint
# --env: sets the model path on the worker
# --min-cuda-version: works around a bug in runpodctl
runpodctl serverless create \
--name "my_worker" \
--hub-id "cm8h09d9n000008jvh2rqdsmb" \
--gpu-id "AMPERE_24" \
--workers-max 3 \
--workers-min 1 \
--model-reference "https://local/$USER_ID/$MODEL_NAME:$MODEL_HASH" \
--env MODEL_NAME="/runpod/model-store/modelrepo-local/models/$USER_ID/$MODEL_NAME/$MODEL_HASH" \
--min-cuda-version "13.0"
```

<Note>
`--model-reference` is only supported with `--hub-id` and GPU endpoints. It is repeatable if you need to attach multiple models to the same endpoint.
</Note>

---

### Step 6: Verify the model is working

Comment thread
lavanya-gunreddi marked this conversation as resolved.
Send a test request to confirm the endpoint is live and the model is accessible. Replace `ENDPOINT_ID` with the ID returned in the previous step:

```bash
curl -s -X POST "https://api.runpod.ai/v2/${ENDPOINT_ID}/runsync" \
-H "Authorization: Bearer $RUNPOD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input": {"prompt": "hello"}}' | jq
```

A successful response confirms the endpoint is running and the model is attached. If the request fails with an auth error, verify that `RUNPOD_API_KEY` is set correctly.

If you prefer a graphical interface to curl, you can also send requests to the worker from the web UI.

---

### Step 7: Clean up

Delete the endpoint after testing to stop accruing spend. Use the web UI or:

```bash
runpodctl serverless delete <endpoint-id>
```
109 changes: 109 additions & 0 deletions serverless/storage/modelrepo/overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
title: "Overview"

@ashleyfrith-alt ashleyfrith-alt Jul 21, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a comment on content but placement of the doc -- right now it's labeled as "storage" within serverless. I would argue since this is essentially a new primitive it deserves its own section similar to Pods / Serverless (with a callout that it only works for Serverless right now and pod support is coming soon). Needs team input though

I would expect the name of the section to also match the feature name "Model Repository" (or whatever it is we land on -- but for now would suggest going with this especially knowing they are confusing Model repo with network volume storage.

sidebarTitle: "Overview"
description: "Store, version, and pre-cache your model files on Runpod infrastructure."
---

<Note>
Model Repo is currently in alpha and is available on Mac and Linux only. Windows support is coming soon.
</Note>

Model Repo is a private model storage service built into Runpod. Upload your model files once, and Runpod caches them directly on your Serverless worker hosts so they are ready before the worker starts — no external download required at cold start time.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

include information about benefits


## How it works

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get some sort of diagram / flowchart to illustrate?


When you create a Serverless endpoint with a model attached, Runpod fetches the model files from storage and caches them on the host machine before the worker container starts. Once the worker boots, the files are already on disk. This eliminates the download step that normally adds seconds or minutes to a cold start.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section is technically true, but this is more what Model Store does. Model Repo is built on Model Store, so it still holds, but it is not specific to Model Repo.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Promptless can you take care of this comment?


Model files are stored in the Runpod ecosystem on private, secure storage. Each uploaded version is content-addressed: after the upload, Runpod computes a hash of the files, and you use that hash to pin a specific version when configuring an endpoint.

The model reference URL format is:

```
https://local/{user-id}/{model-name}:{hash}
```

You pass this URL as the `--model-reference` flag when creating or updating an endpoint. Runpod uses it to know exactly which version of which model to cache on the host.

## What you can upload

Model Repo accepts model files in any format. There is no restriction on file type — you can upload PyTorch checkpoints, GGUF files, safetensors, ONNX models, or any other format your worker needs. Runpod performs no type checking on uploads.

The maximum size for an individual file is 5TB, and uploaded model files are retained indefinitely.

The total storage limit per account and per model is still being finalized.

## How the model is available inside the worker

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the commands here feel more relevant to a quickstart since they can't actually "use" model repo yet with this page. Not that it doesn't make sense to provide commands on an overview, but if you look at Flash overview page that gives some quickstart code then a tiny bit of information on how it's actually working. So perhaps this info should live in quickstart instead, including how it works for Serverless.


When the worker starts, your model files are available at this path inside the container:

```
/runpod/model-store/modelrepo-local/models/{user-id}/{model-name}/{model-hash}
```

Pass this path to the worker as an environment variable using the `--env` flag when creating the endpoint:

```
--env MODEL_NAME="/runpod/model-store/modelrepo-local/models/$USER_ID/$MODEL_NAME/$MODEL_HASH"
```

Your handler function reads `MODEL_NAME` to know where to load the model from. Model Repo only handles delivering the files to the host — your handler is fully responsible for loading the model and processing requests.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think they need to write a handler with this for a queue-based endpoint because I can just deploy one and it works. So somehow we have packaged the handler within

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that only works depending on the specific model and template you use, but I could be wrong.


/* [ENGINEERING: Marcin's question — does Runpod do any additional wrapping of the model (e.g., auto-adding /ping, adding a handler wrapper)? The current doc says users write their own handler. Confirm this is accurate.] */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not do anything special around the model besides mounting it.


For queue-based endpoints, you write a handler function that receives requests, loads the model from `MODEL_NAME`, runs inference, and returns results. For load balancing endpoints (FastAPI, Flask, etc.), your server process loads the model from that path on startup.

## Model Repo vs network volumes

Both Model Repo and [network volumes](/storage/network-volumes) can make model files available to Serverless workers. The key difference is when and how the files are delivered.

| | Model Repo | Network volume |
|---|---|---|
| **Delivery** | Cached on host before worker starts | Mounted as a network filesystem at runtime |
| **Cold start impact** | Lower — files already on disk | Higher — network mount adds latency |
| **Best for** | Fixed, versioned model weights | Frequently changing files, shared state |
| **Versioning** | Built-in, content-addressed by hash | Manual — you manage file paths yourself |
| **Multi-worker sharing** | Not shared across workers | Shared across all workers on the same volume |
| **Storage billing** | /* [ENGINEERING: how is Model Repo storage billed? $/GB/month?] */ | $0.07/GB/month |

Use Model Repo when:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we get these down to a single bullet point / sentence? It's excellent info but taking up decent amount of screen space. I wonder if this could even potentially break out to its own doc..? We've got a lot of info on this overview. Feels like this info + the "switching from your current setup" could potentially be its own short doc

note I am unfamiliar with documentation best practices, I have intuitions about what content belongs in overview vs quickstart vs other things but take what I say with 2c

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also call out in this section that Model Repo gives more flexibility around being in multiple DCs, since a Network Volume is tied to a datacenter, and Model Repo can pull the same model into any DC.

- You have a fixed set of model weights you want to distribute reliably to workers.
- You want shorter cold starts without depending on HuggingFace or any external download source.
- You need version control over exactly which model checkpoint is deployed.

Use a network volume when:
- Workers need to read and write shared files during a run (e.g., checkpoints, intermediate outputs).
- Your files change frequently and you want all workers to see the latest version immediately.
- You need the same set of files available to many concurrent workers simultaneously.

## Switching from your current setup

The effort to adopt Model Repo depends on how you currently deliver your model files to workers.

**If you download from HuggingFace or a URL at cold start:**

1. Upload your model files to Model Repo using `runpodctl`.
2. Record the model URL (contains the user ID, name, and hash).
3. Add `--model-reference` to your endpoint configuration.
4. Remove the download logic from your handler or startup script.

The files will be available at a local path when the worker starts, so your loading code changes from a `hf_hub_download()` call (or equivalent) to a local file open. Everything downstream — your handler function structure, request format, response format — stays the same.

**If your model weights are baked into your Docker image:**

Baking weights into a Docker image inflates image size and increases cold start times (Runpod must pull the full image on each new host). Moving weights out into Model Repo and shrinking your Docker image typically improves cold start performance.

To migrate:
1. Remove the model weights from your Dockerfile and rebuild without them.
2. Upload the weights separately to Model Repo.
3. Update your endpoint to reference the model URL.
4. Update your worker code to load the model from the local path instead of from within the image.

/* [ENGINEERING: Anything specific users need to do if their model has baked images (e.g., embedded image assets in weights)? Any known edge cases?] */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would depend on how their current image uses that baked in model. They may need to reconfigure it to use the Model Repo model's path, rather than whatever is baked in.


**If you cache models on a network volume:**

You can switch to Model Repo if your model weights are stable and you do not need workers to write to the same storage location. The primary benefit is faster host-level caching and simpler version management. If your workers currently write to the network volume (for checkpoints, fine-tuning outputs, etc.), keep the network volume for that purpose.

## Getting started

See [Model Repo testing](/serverless/model-repo/testing) for a step-by-step guide to uploading a model and deploying it to a Serverless endpoint.
40 changes: 40 additions & 0 deletions serverless/storage/modelrepo/security.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: "Security"
sidebarTitle: "Security"
description: "How Model Repo stores and protects your model data."
---

## Storage

Model Repo stores your model files in Runpod's infrastructure, backed by [Cloudflare R2](https://developers.cloudflare.com/r2/). Your data is isolated to your Runpod account and is not accessible to other users.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, I am not sure if we want to specifically call out R2. But that is probably a Product decision.


## Encryption

All model data is encrypted at every stage:

- **At rest**: AES-256-GCM encryption, applied by default to all objects stored in Cloudflare R2.
- **In transit**: TLS encryption for all transfers — between your machine and Runpod when uploading, and between Runpod's systems when caching models on worker hosts.

## Your data is yours

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feels like this belongs in overview -- I'm envisioning overview through more of a storytelling approach; quick diagram how it works, your data is yours, here's link to compliance docs if you want them (don't need a separate section called compliance imo -- just link it under the your data yours section


Runpod does not access, analyze, or use your model files for any purpose. Models stored in Model Repo are not used for training, evaluation, or any other internal purpose. Only you can access your models through your account credentials.

## Compliance

/* [ENGINEERING: Ben Rosenberg mentioned linking to SOC1/SOC2 certs. What certifications does Runpod currently hold, and where are they published? Confirm the correct link for Runpod's security/compliance page.] -->

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also double check that R2 also holds those certs and that the way we use it is also in line with those certs.


Runpod maintains industry-standard security certifications. For a full overview of Runpod's security posture, certifications, and policies, see [runpod.io/security](https://runpod.io/security).

## Frequently asked questions

**Does Runpod use my models to train other models?**

No. Your model files are stored privately and are never used by Runpod for any purpose.

**Can other Runpod users access my models?**

No. Models are scoped to your Runpod account. Other users cannot access or list your models.

**Who manages the storage infrastructure?**

Cloudflare R2 is the underlying object storage backend. Cloudflare applies encryption-at-rest using AES-256-GCM by default. Runpod manages the access layer and authentication — only your Runpod API key can retrieve your models.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above R2 comment.

Loading
Loading