Skip to content

Deploy (push) an application

Info

Learn the concepts and fundamentals of deploying applications in the Explanation page.

Deploying applications to Nextmv Cloud allows you to take full advantage of the Nextmv Platform. Once an application has been pushed, you can execute remote runs, and perform experiments and tests.

Push an application to Nextmv Cloud using the Application.push method. Stand in the same location as the app's root directory, this is, where the app.yaml manifest is located.

import os

from nextmv import cloud

client = cloud.Client(api_key=os.getenv("NEXTMV_API_KEY"))
app = cloud.Application.get(client=client, id="jumping-hare")
app.push(verbose=True)
uv run main.py
💽 Starting build for Nextmv application.
🐍 Bundling Python dependencies.
     34/34 compressed dependencies found in cache.
📋 Copying files listed in "app.yaml" manifest.
💾 Compressing application into tarball.
    🛠️  Appending application files.
📦 Packaged application (2 app files, 51.76 MiB with dependencies).
🌟 Pushing to application: "jumping-hare".
💥️ Successfully pushed to application: "jumping-hare".
{
  "app_id": "jumping-hare",
  "endpoint": "https://api.cloud.nextmv.io",
  "instance_url": "v1/applications/jumping-hare/runs?instance_id=latest"
}

You don't have to be standing in the same location as the app's root dir if you don't want to. You can use the app_dir keyword argument to specify a different path to the app's root directory. Additionally, you may use the manifest keyword argument, passing a Manifest object, to use an entirely different manifest.

Unlike the CLI, Application.push only pushes the app: it does not create a version or an instance for you. To do so, use the Application.new_version method and, optionally, either the Application.new_instance method or the Application.update_instance method.

Tip

It is a best practice to create a version for every push to Nextmv Cloud. This allows you to keep track of changes made to the decision model.

Use the following methods after pushing to create a version and, optionally, link it to an instance:

  • Application.new_version: creates a new version. Use the id keyword argument to specify a custom version ID. If not provided, a random ID will be generated.
  • Application.new_instance: creates a new instance and links it to a version. Requires the version_id keyword argument. Use the id keyword argument to specify a custom instance ID.
  • Application.update_instance: updates an existing instance to point to a new version. Requires the id and version_id keyword arguments.

Pushes the app and creates a new version with a random ID.

import os

import nextmv
from nextmv import cloud

client = cloud.Client(api_key=os.getenv("NEXTMV_API_KEY"))
app = cloud.Application.get(client=client, id="jumping-hare")
app.push(verbose=True)

version = app.new_version(description="Version created automatically from push.")

nextmv.write(version.to_dict())
uv run main.py
💽 Starting build for Nextmv application.
🐍 Bundling Python dependencies.
     34/34 compressed dependencies found in cache.
📋 Copying files listed in "app.yaml" manifest.
💾 Compressing application into tarball.
    🛠️  Appending application files.
📦 Packaged application (2 app files, 51.76 MiB with dependencies).
🌟 Pushing to application: "jumping-hare".
💥️ Successfully pushed to application: "jumping-hare".
{
  "app_id": "jumping-hare",
  "endpoint": "https://api.cloud.nextmv.io",
  "instance_url": "v1/applications/jumping-hare/runs?instance_id=latest"
}
{
  "id": "version-0ihb5e8s",
  "application_id": "jumping-hare",
  "name": "version-0ihb5e8s",
  "description": "Version created automatically from push.",
  "executable": {
    "id": "version-0ihb5e8s",
    "user_email": "sebastian@nextmv.io",
    "uploaded_at": "2026-07-28T16:25:41.011044Z",
    "requirements": {
      "executable_type": "python",
      "runtime": "ghcr.io/nextmv-io/runtime/python:3.11"
    }
  },
  "created_at": "2026-07-28T16:25:42.493036Z",
  "updated_at": "2026-07-28T16:25:42.493036Z"
}

Creates a new instance with the provided ID and links it to the newly created version.

import os

import nextmv
from nextmv import cloud

client = cloud.Client(api_key=os.getenv("NEXTMV_API_KEY"))
app = cloud.Application.get(client=client, id="jumping-hare")
app.push(verbose=True)

version = app.new_version(description="Version created automatically from push.")
instance = app.new_instance(
    version_id=version.id,
    id="dev",
    description="Instance created automatically from push.",
)

nextmv.write(instance.to_dict())
uv run main.py
💽 Starting build for Nextmv application.
🐍 Bundling Python dependencies.
     34/34 compressed dependencies found in cache.
📋 Copying files listed in "app.yaml" manifest.
💾 Compressing application into tarball.
    🛠️  Appending application files.
📦 Packaged application (2 app files, 51.76 MiB with dependencies).
🌟 Pushing to application: "jumping-hare".
💥️ Successfully pushed to application: "jumping-hare".
{
  "app_id": "jumping-hare",
  "endpoint": "https://api.cloud.nextmv.io",
  "instance_url": "v1/applications/jumping-hare/runs?instance_id=latest"
}
{
  "id": "dev",
  "application_id": "jumping-hare",
  "version_id": "version-5cmtggsp",
  "name": "dev",
  "description": "Instance created automatically from push.",
  "configuration": {
    "execution_class": "6c9500mb870s",
    "queuing": {
      "priority": 6,
      "disabled": false
    }
  },
  "locked": false,
  "created_at": "2026-07-28T16:26:04.151551Z",
  "updated_at": "2026-07-28T16:26:04.151551Z"
}

Updates an existing instance and links it to the newly created version.

import os

import nextmv
from nextmv import cloud

client = cloud.Client(api_key=os.getenv("NEXTMV_API_KEY"))
app = cloud.Application.get(client=client, id="jumping-hare")
app.push(verbose=True)

version = app.new_version(description="Version created automatically from push.")
instance = app.update_instance(id="prod", version_id=version.id)

nextmv.write(instance.to_dict())
uv run main.py
💽 Starting build for Nextmv application.
🐍 Bundling Python dependencies.
     34/34 compressed dependencies found in cache.
📋 Copying files listed in "app.yaml" manifest.
💾 Compressing application into tarball.
    🛠️  Appending application files.
📦 Packaged application (2 app files, 51.76 MiB with dependencies).
🌟 Pushing to application: "jumping-hare".
💥️ Successfully pushed to application: "jumping-hare".
{
  "app_id": "jumping-hare",
  "endpoint": "https://api.cloud.nextmv.io",
  "instance_url": "v1/applications/jumping-hare/runs?instance_id=latest"
}
{
  "id": "prod",
  "application_id": "jumping-hare",
  "version_id": "version-2it1si1h",
  "name": "prod",
  "description": "Instance created automatically from push at 2026-07-22T22:30:37Z",
  "configuration": {
    "execution_class": "6c9500mb870s",
    "queuing": {
      "priority": 6,
      "disabled": false
    }
  },
  "locked": false,
  "created_at": "2026-07-22T22:30:39.092455Z",
  "updated_at": "2026-07-28T16:26:19.770951Z"
}

Cache for Python dependencies

If you are working with a Python application, the SDK will download and bundle all the dependencies that are specified in the python section of the app.yaml. To avoid re-downloading and re-compressing dependencies every time you push, the SDK caches the compressed dependencies.

The default behavior when pushing is to use the cache for dependencies. If you want to skip the cache, you can use the no_cache keyword argument.

import os

from nextmv import cloud

client = cloud.Client(api_key=os.getenv("NEXTMV_API_KEY"))
app = cloud.Application.get(client=client, id="jumping-hare")
app.push(verbose=True, no_cache=True)
uv run main.py
💽 Starting build for Nextmv application.
🐍 Bundling Python dependencies - caching disabled.
    🐇 Downloading and compressing 34 dependencies from package index.
📋 Copying files listed in "app.yaml" manifest.
💾 Compressing application into tarball.
    🛠️  Appending application files.
📦 Packaged application (2 app files, 51.76 MiB with dependencies).
🌟 Pushing to application: "jumping-hare".
💥️ Successfully pushed to application: "jumping-hare".
{
  "app_id": "jumping-hare",
  "endpoint": "https://api.cloud.nextmv.io",
  "instance_url": "v1/applications/jumping-hare/runs?instance_id=latest"
}

You can manage the cache with the nextmv.cache module. The policy used for the cache is LRU (Least Recently Used) eviction. The number and size of cached dependencies is limited to avoid using too much disk space.

Get cache information

Use the get_cache function to retrieve information about the cache, such as the size of the cache and the number of cached dependencies.

import json

from nextmv.cache import get_cache

cache_info = get_cache()

print(json.dumps(cache_info, indent=2))
uv run main.py
{
  "num_dependencies": 34,
  "total_size": "51.77 MiB",
  "dependencies": [
    {
      "key": "f38bab26ffb0c90c1a9de0d59fb32d7d9f9a350b9f029952112ba04e6c10cd64",
      "name": "xyzservices",
      "version": "2026.3.0",
      "last_used_at": "2026-07-28T16:26:10.482054+00:00",
      "python_version": "3.11",
      "platform": "aarch64-manylinux_2_34",
      "size": "85.15 KiB"
    },
    ...
    {
      "key": "b1fb017606938935a84e95503eae31007936fd0dd5b5c50ab97330c81c843ef3",
      "name": "annotated-doc",
      "version": "0.0.5",
      "last_used_at": "2026-07-28T16:26:10.474334+00:00",
      "python_version": "3.11",
      "platform": "aarch64-manylinux_2_34",
      "size": "4.68 KiB"
    }
  ]
}

Clear the cache

Warning

Clearing the cache will remove all cached dependencies and it is a permanent action.

Use the clear_cache function to clear the cache.

from nextmv.cache import clear_cache, format_bytes

num_deps, total_bytes = clear_cache()

print(f"Deleted {num_deps} dependencies ({format_bytes(total_bytes)}) from the cache.")
uv run main.py
Deleted 34 dependencies (51.77 MiB) from the cache.