> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowx.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# ModPod setup

> Configure the ModPod service for ML model serving with LightGBM, scikit-learn, and SHAP explainability.

ModPod is a standalone Python service. It does not depend on Kafka, Keycloak, or object storage — model artifacts and the model registry live on a local persistent volume.

***

## Dependencies

ModPod is self-contained. It does not require any other FlowX infrastructure service to run.

* **Persistent volume** — required for model artifacts and the SQLite registry
* **Identity provider** — not used; authentication is a static bearer token
* **Kafka** — not used
* **Object storage (S3/MinIO)** — not used; models are stored on the mounted volume

***

## Capabilities

* Upload model packages as ZIP archives with a `metadata.json` manifest
* Manage model registry (list, fetch, delete by name/version)
* Load models into memory on demand
* Run inference with SHAP-based top-factor explanations
* Support for **LightGBM** (Booster text format) and **Logistic Regression** (scikit-learn, joblib-serialized)

***

## Authentication

ModPod uses a static bearer token. Set the `AUTHORIZATION_APIKEY` environment variable and include the token on every request except the health check:

```http theme={"dark"}
Authorization: Bearer <AUTHORIZATION_APIKEY>
```

<Warning>
  The API key is a static secret. Store it in a Kubernetes `Secret` (or equivalent) and never commit it to source control.
</Warning>

***

## API endpoints

All endpoints are prefixed with `/modpod`.

### Health

| Method | Path | Auth | Description |
| - | - | - | - |
| `GET` | `/modpod/info/healthcheck` | None | Service health check |

### Model upload

| Method | Path | Auth | Description |
| - | - | - | - |
| `POST` | `/modpod/upload` | Bearer | Upload a ZIP archive containing model files and `metadata.json` |

The ZIP must contain a `metadata.json` file with `name` and `version` fields. Files are extracted to `<MODPOD_MODELS_DIR>/<name>/<version>/`.

### Model registry

| Method | Path | Auth | Description |
| - | - | - | - |
| `GET` | `/modpod/models` | Bearer | List all registered models |
| `GET` | `/modpod/models/{name}` | Bearer | Get model details and versions |
| `GET` | `/modpod/models/{name}/versions` | Bearer | List versions for a given model |
| `DELETE` | `/modpod/models/{name}/{version}` | Bearer | Delete a specific model version |
| `DELETE` | `/modpod/models` | Bearer | Delete all models |

### Inference

| Method | Path | Auth | Description |
| - | - | - | - |
| `POST` | `/modpod/inference/load` | Bearer | Load a model into memory |
| `POST` | `/modpod/inference/predict` | Bearer | Run prediction on a loaded model |

#### Predict request

```json theme={"dark"}
{
  "model_name": "call-propensity",
  "model_version": "1.0",
  "model_type": "propensity",
  "input_data": {
    "feature1": 0.5,
    "feature2": "category_a",
    "feature3": 100
  }
}
```

#### Predict response

```json theme={"dark"}
{
  "output_data": {
    "model": "call-propensity:1.0",
    "input": { "...": "..." },
    "result": {
      "prediction": 0.73,
      "top_factors": "feature1=0.50 (avg=0.30); feature2=category_a"
    }
  }
}
```

***

## Supported model types

| Type | Format | File name |
| - | - | - |
| **LightGBM** | Booster text format | `encoders/model-{type}.txt` |
| **Logistic Regression** | joblib-serialized scikit-learn model | `encoders/model-{type}.joblib` |

Both types produce SHAP-based top-factor explanations alongside the prediction. LightGBM uses the built-in `pred_contrib` output; Logistic Regression uses `shap.LinearExplainer`.

***

## Model package structure

Model packages are uploaded as ZIP archives with the following layout:

```text theme={"dark"}
model.zip/
├── metadata.json
└── encoders/
    ├── model-{type}.txt         # LightGBM model (or .joblib for Logistic Regression)
    ├── {type}-feature-context.csv  # Feature metadata (mean, direction, type)
    ├── standard_scaler.pkl      # StandardScaler (Logistic Regression only)
    ├── shap_background.pkl      # SHAP background data (Logistic Regression only)
    └── {feature}-classes.pkl    # LabelEncoder per categorical feature (LightGBM)
```

The `metadata.json` file must contain at least `name` and `version`:

```json theme={"dark"}
{
  "name": "call-propensity",
  "version": "1.0",
  "description": "Propensity-to-call scoring model"
}
```

***

## Environment variables

### Authentication

| Environment Variable | Description | Default Value |
| - | - | - |
| `AUTHORIZATION_APIKEY` | Bearer token required on all authenticated endpoints. | - (required) |

### Storage

| Environment Variable | Description | Default Value |
| - | - | - |
| `MODPOD_MODELS_DIR` | Directory where uploaded model artifacts are stored. Mount a persistent volume here. | `./models` |
| `MODPOD_DATABASE_URL` | Database URL for the model registry. SQLite is used by default. | `sqlite:///modpod.db` |
| `MODPOD_DB_PATH` | SQLite file path. Used only when `MODPOD_DATABASE_URL` is not set. | `./modpod.db` |

### Server

| Environment Variable | Description | Default Value |
| - | - | - |
| `GUNICORN_WORKERS` | Number of Gunicorn worker processes. | `1` |
| `GUNICORN_TIMEOUT` | Request timeout in seconds. | `600` |

<Info>
  Recommended worker count is `1`. Inference is CPU-bound and loaded models are held in per-process memory; additional workers multiply the memory footprint without increasing throughput for a single model.
</Info>

### CORS

| Environment Variable | Description | Default Value |
| - | - | - |
| `APPLICATION_CORS_ALLOWORIGIN` | Comma-separated list of allowed origins. Set to the frontend origin(s) that call ModPod. | - |
| `APPLICATION_CORS_ALLOW_HEADERS` | Comma-separated list of allowed request headers. | Standard FlowX headers |
| `APPLICATION_CORS_ALLOW_METHODS` | Comma-separated list of allowed HTTP methods. | `GET,PUT,POST,DELETE,PATCH,OPTIONS` |

***

## Deployment

ModPod is packaged as a Docker image based on `python:3.13.3-slim-bookworm` and runs as a non-root user.

| Setting | Value |
| - | - |
| Container port | `8080` |
| Health check path | `/modpod/info/healthcheck` |
| Models directory (in container) | `/code/models` |
| SQLite database (in container) | `/code/modpod.db` |

### Resource recommendations

| Resource | Recommendation |
| - | - |
| Memory | 512 MB – 1 GB, depending on the number and size of loaded models |
| CPU | 1 vCPU (inference is CPU-bound) |
| Gunicorn workers | `1` |
| Persistent volume | Minimum `5Gi` for `/code/models` (grows with the number of models) |

<Warning>
  The SQLite registry is file-based and stored on the same volume as model artifacts. To scale ModPod horizontally, switch to an external database by setting `MODPOD_DATABASE_URL` to a shared database URL.
</Warning>

***

## Validation

<Check>
  Health check returns `200 OK`:

  ```bash theme={"dark"}
  curl http://<modpod-host>/modpod/info/healthcheck
  ```
</Check>

<Check>
  Authenticated listing returns an empty list (fresh install) or your registered models:

  ```bash theme={"dark"}
  curl -H "Authorization: Bearer $AUTHORIZATION_APIKEY" \
    http://<modpod-host>/modpod/models
  ```
</Check>

***

## Related resources

<CardGroup cols={2}>
  <Card title="Ingress configuration" icon="network-wired" href="./ingress-configuration">
    Routing and CORS for FlowX services
  </Card>

  <Card title="Setup guides overview" icon="list" href="./setup-guides-overview">
    Full list of FlowX service setup guides
  </Card>
</CardGroup>


## Related topics

- [AI Platform setup](/5.9/setup-guides/ai-platform-setup.md)
- [Speech to Text setup](/5.9/setup-guides/speech-to-text-setup.md)
- [FlowX Events Gateway setup](/5.9/setup-guides/events-gateway-setup.md)
- [Webhook Gateway setup](/5.9/setup-guides/webhook-gateway-setup.md)
- [Organization Manager setup](/5.9/setup-guides/organization-manager-setup.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.