Skip to main content

Polars On-Prem over Ray

Runs the Polars On-Prem scheduler and workers as Ray actors.

Quickstart

Prerequisites for a completely local test deployment:

  • A Polars On-Prem binary accessible on the machine
  • A Polars On-Prem license.json file, or a valid service account
  • A Python virtual environment:
uv venv
source .venv/bin/activate
uv pip install polars-cloud-ray

It will also install ray as a dependency. Note that a few things need to be set up for the Polars On-Prem cluster to function properly:

# path to libpython3.x.so
export LD_LIBRARY_PATH=$(python -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")

# need to match the config if manually changed
mkdir --parents /tmp/polars/{anonymous-results,license,observatory,shuffle-data,temporary-data}

This latter can be started using the following command:

ray start \
  --dashboard-host=0.0.0.0 \
  --disable-usage-stats \
  --head \
  --port="6379" \
  --ray-client-server-port="10001" \
  --resources='{"head":1}' # pinning

If you do not already have one, create a Polars service account through the cloud portal. Pull the Polars On-Prem binary locally (available versions are listed on our Releases page), and remember its local path:

wget https://cdn.onprem.pola.rs/polars-on-premises-<VERSION>-linux-x64

Spawn a local multinode cluster:

import polars as pl
import polars_cloud as pc
import ray

from polars_cloud_ray.cluster import PolarsRayCluster
from polars_cloud_ray.config import (
    PolarsObservatoryConfig,
    PolarsRayClusterConfig,
    PolarsSchedulerConfig,
    PolarsServiceAccountLicenseConfig,
    PolarsWorkerConfig,
)

config = PolarsRayClusterConfig(
    binary_path="/path/to/binary",
    num_workers=4,
    single_host_cluster=True,
    license=PolarsServiceAccountLicenseConfig(
        workspace_id="<WORKSPACE_ID>",
        client_id="<SERVICE_ACCOUNT_ID>",
        client_secret="<SERVICE_ACCOUNT_SECRET>",
    ),
    scheduler=PolarsSchedulerConfig(...),
    worker=PolarsWorkerConfig(...),
)

ray.init(address="auto", namespace=config.cluster_id)
cluster = PolarsRayCluster(config)
cluster.start()

print(
    pl.LazyFrame({"a": [1, 2, 3], "b": [4, 4, 5]})
    .with_columns(pl.col("a").max().over("b").alias("c"))
    .remote(pc.ClusterContext(uri=f"http://{cluster.get_client_addr()}"))
    .execute()
    .head
)

cluster.stop()
ray.shutdown()

or:

import polars as pl
import ray

from polars_cloud_ray.config import (
    PolarsObservatoryConfig,
    PolarsRayClusterConfig,
    PolarsSchedulerConfig,
    PolarsServiceAccountLicenseConfig,
    PolarsWorkerConfig,
)
from polars_cloud_ray.context import RayClusterContext

config = PolarsRayClusterConfig(
    binary_path="/path/to/binary",
    num_workers=4,
    single_host_cluster=True,
    license=PolarsServiceAccountLicenseConfig(
        workspace_id="<WORKSPACE_ID>",
        client_id="<SERVICE_ACCOUNT_ID>",
        client_secret="<SERVICE_ACCOUNT_SECRET>",
    ),
    scheduler=PolarsSchedulerConfig(...),
    worker=PolarsWorkerConfig(...),
)

ray.init(address="auto", namespace=config.cluster_id)

with RayClusterContext(config) as ctx:
    print(
        pl.LazyFrame({"a": [1, 2, 3], "b": [4, 4, 5]})
        .with_columns(pl.col("a").max().over("b").alias("c"))
        .remote(ctx)
        .execute()
        .head
    )

ray.shutdown()

In case Ray is running on a single host, set the single_host_cluster configuration attribute to True to offset worker ports and avoid socket collisions.

The actors are running in detached mode and survive past the script: one can reconnect with the same ray.init() and cluster gymnastics from another process. To clean all actors and underlying processes, Ray itself needs to be shutdown using the following command:

ray stop --force

Autoscaling

A dedicated scaler actor, pinned to the scheduler node, runs an HTTP server to handle scaling requests sent by the underlying binary. These requests are relayed to the scheduler actor, which in turn adds or removes Ray worker actors in response.

Enable it via PolarsScalingConfig on the scheduler, and optionally set min_workers and/or max_workers on the cluster config to bound how far it may scale. Note the cluster always starts num_workers workers: the bounds are reported back to the binary on GET /scale_config, seeded into max_workers_per_query, and only enforced on rescaling, where a POST /scale_to count outside them is clamped. Requesting more workers is done via the client: .distributed(min_workers=X).

The HTTP server is unauthenticated and binds 127.0.0.1. It accepts only application/json bodies, and ignores worker names that are not worker actors.

License server

PolarsLicenseServer manages a pc-license-server process, Polars On-Prem's offline license server: clusters point their configuration at it via PolarsLicenseServerConfig(uri=...) and it validates them locally, tracking usage into signed reports it periodically emits (and optionally uploads to the control plane).

It is standalone: unlike the scheduler/worker/scaler, it is not wired into PolarsRayCluster. It is meant to be a single, long-lived service that any number of separate clusters register against, so its lifecycle (and Ray namespace) is managed independently, and it should be started before any cluster that points at it.

import ray

from polars_cloud_ray.config import PolarsLicenseServerRuntimeConfig
from polars_cloud_ray.license_server import PolarsLicenseServer

config = PolarsLicenseServerRuntimeConfig(
    report_dir="/var/log/polars/license-server",
    license_path="/etc/polars/license.json",
    tls_bundle_path="/etc/polars/tls-bundle.pem",
)

ray.init(address="auto", namespace="license-server")
license_server = PolarsLicenseServer(config)
license_server.start()

A cluster then validates against it with:

from polars_cloud_ray.config import PolarsLicenseServerConfig

license = PolarsLicenseServerConfig(uri=license_server.get_bind_addr())

To reconnect to (or stop) an already-running license server from another process, call ray.init() with the same namespace it was started under, then PolarsLicenseServer(config).start() (reconnects) or .stop().

Resource requests and limits

Four parameters control resource usage:

  • cpus_hint / memory_hint: forwarded verbatim as Ray's own num_cpus / memory actor options, and used by Ray for bin-packing only; not enforced at the OS level.
  • cpu_reserved: a scheduling/accounting hint consumed internally by the binary for task placement and reported to the observatory; never enforced.
  • memory_limit: enforced by the binary itself via cgroups; but only if a delegated cgroup subtree is made available (e.g., inside a container or a scoped systemd-run).

A plain session/SSH shell does not provide one (everything lives flatly in one cgroup), so memory_limit fails outright with the following message:

Ensure cgroup is mounted and subgroups are delegated, or disable the memory limit in the configuration file.

What "enforced" actually means

Hitting memory.max does not by itself kill a process: the kernel attempts direct reclaim and retries, and only resorts to the OOM killer once reclaim genuinely cannot free anything more. In practice this usually means throttling to a crawl rather than a hard failure.

Release files for polars-cloud-ray 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for polars-cloud-ray 0.1.1
File Size Uploaded
polars_cloud_ray-0.1.1.tar.gz 30.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for polars-cloud-ray 0.1.1
File Interpreter ABI Platform
polars_cloud_ray-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 58.3 kB

Release files / polars_cloud_ray-0.1.1.tar.gz

Download URL polars_cloud_ray-0.1.1.tar.gz
Size 30.2 kB
Tags Source
SHA-256 checksum
How to use checksums
2abd844dc4c6a877c931af4e95a4d34af37187171173bd9c3ad5b9a353335d58
BLAKE2b-256 checksum
How to use checksums
5580137d3d93247935da88ca88ac0d65a6ef749975e2e127e5dc12caff4bc680
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release files / polars_cloud_ray-0.1.1-py3-none-any.whl

Download URL polars_cloud_ray-0.1.1-py3-none-any.whl
Size 28.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
857a4535e40e4e1510b789a35102bd04faa50dd43a304d55a50be3a2607aca3a
BLAKE2b-256 checksum
How to use checksums
6975b5f2b002474a4fa70e2bc2151127b23fcda3fa4028cc45f54f98481b4011
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page