Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Redis Feature Form Python SDK

redis-featureform is the Python SDK and ff CLI for Redis Feature Form.

Redis Feature Form gives data and ML teams a declarative workflow for defining providers, datasets, transformations, entities, features, labels, training sets, and feature views in Python while keeping existing offline data systems in place. Redis is the low-latency online store for feature serving.

Install from PyPI as redis-featureform, then import it in Python as featureform.

Official Redis Feature Form docs:

  • Overview: https://redis.io/docs/latest/develop/ai/featureform/overview/
  • Quickstart: https://redis.io/docs/latest/develop/ai/featureform/quickstart/
  • Documentation hub: https://redis.io/docs/latest/develop/ai/featureform/

Install

pip install redis-featureform

Optional extras:

pip install "redis-featureform[otel]"
pip install "redis-featureform[pyspark]"

What Redis Feature Form Does

Redis Feature Form helps you:

  • register offline systems and Redis as providers
  • define feature engineering resources as Python code
  • submit a complete resource graph into a workspace with ff apply or client.apply()
  • inspect the resulting plan before execution
  • query datasets and training sets over Arrow Flight
  • serve online feature values from Redis-backed feature views

Core Workflow

The Redis Feature Form workflow is:

  1. Create a workspace.
  2. Register providers for offline systems and the Redis online store.
  3. Author resources in Python.
  4. Apply or merge the resource graph into the workspace.
  5. Let Redis Feature Form plan and run the required execution work.
  6. Query offline results for training or fetch online features for inference.

Connection Defaults

The Python ff CLI and Client() default to the gRPC control-plane endpoint on localhost:9090. REST remains available only when explicitly selected with --transport rest, FEATUREFORM_TRANSPORT=rest, or transport="rest".

Bare loopback gRPC targets such as localhost:9090 default to plaintext for local development. Remote gRPC targets default to TLS unless plaintext is requested explicitly with --no-tls in the CLI or with an http://host:port gRPC target in the SDK.

Featureform also exposes a REST API on port 8080. If gRPC and REST run in the same FEATUREFORM_SERVER_MODE=all process, they share in-memory state. If they run as separate processes with STATE_BACKEND=memory, each process has its own state store; use STATE_BACKEND=postgres to share state across processes.

Interactive authentication

Current servers advertise the login credential contract. ff auth login follows that default: paired OIDC authentication when enabled, or OAuth resource-server authentication when only resource tokens are supported. Use --credential-mode resource_token to explicitly select OAuth resource-server authentication when both are enabled, or --credential-mode id_token_pair to require paired OIDC authentication. Direct PKCE/device login with --issuer-url requires this option. Development password login supports only OAuth resource-server authentication.

Paired sessions store the ID token and access token together in protected session format version 2. Existing sessions require a fresh login. Keyring remains the default; file storage requires explicit FEATUREFORM_AUTH_STORAGE=file and uses private file permissions. Python clients reuse the whole pair for matching profile/deployment targets, including serving and Arrow Flight.

Refresh preserves the original granted scopes, including openid. An expired ID token, changed subject, or incompatible token pair requires re-login; the CLI never silently switches a paired session to resource-token authentication. Java and Featureform UI paired-session support are outside this RC.

Run make test-paired-auth from the repository root after installing Python and dashboard dependencies and the Playwright Chromium browser. This starts isolated OIDC/API/dashboard processes and verifies paired OIDC authentication and OAuth resource-server authentication, each enabled independently and together. Coverage includes login, refresh, expiry, re-login, authorization, and Python transport forwarding. Its dedicated bin/featureform-paired-auth-test binary has test-only licensing settings. The shared Python/Java session fixture is in contracts/examples/auth/.

Core Concepts

  • Workspace: logical boundary for a Redis Feature Form resource graph
  • Provider: connection to an external system such as Postgres, Snowflake, Spark, S3, Iceberg, or Redis
  • Resource: Python declaration of an entity, dataset, transformation, feature, label, training set, or feature view
  • Apply: single-shot workspace update that submits one combined resource set, computes a delta, and optionally runs an apply job
  • Merge: apply strategy that preserves omitted resources already present in the workspace
  • Execution mode: planning mode for runtime work, currently NORMAL, UPDATE, or FULL_REMATERIALIZE
  • Training set: offline, model-ready dataset composed from features and labels
  • Feature view: online-serving surface backed by Redis for inference-time lookup

Connect And Register Providers

The CLI is usually the fastest way to bootstrap Redis Feature Form resources:

ff --server grpc.example.com:443 --transport grpc auth login

ff --server grpc.example.com:443 --transport grpc \
  workspace create fraud-detection

ff --server grpc.example.com:443 --transport grpc \
  provider register analytics-postgres \
  --workspace fraud-detection \
  --type postgres \
  --pg-host postgres.example.com \
  --pg-port 5432 \
  --pg-database analytics \
  --pg-username ff_user \
  --pg-password-secret env:PG_PASSWORD

ff --server grpc.example.com:443 --transport grpc \
  provider register online-store \
  --workspace fraud-detection \
  --type redis \
  --redis-host redis.example.com \
  --redis-port 6379

For identity providers that require Authorization Code with PKCE instead of Device Authorization Flow, register a CLI redirect URI with the IdP and run:

ff --server grpc.example.com:443 --transport grpc auth login \
  --login-method authorization_code_pkce \
  --redirect-uri https://app.example.com/cli/callback

The CLI prints the authorization URL, then prompts for the full redirected URL or raw authorization code. The full redirected URL is preferred because it lets the CLI validate the login state locally; raw codes are accepted as a fallback and are verified by PKCE during token exchange. If your IdP requires a confidential CLI client, pass --login-client-secret or FEATUREFORM_LOGIN_CLIENT_SECRET; the secret is used only for that login and is not persisted.

Providers are registered separately from apply. Resource definitions then refer to those provider names when you define datasets, transformations, training sets, and Redis-backed feature views.

What ff apply Does

ff apply is the main authoring workflow in Redis Feature Form.

At a high level it:

  1. loads one Python entry file or package directory
  2. collects resources from either an explicit resources = [...] list or the global registry
  3. serializes the full resource graph into one request for one workspace
  4. compares the submitted graph with the current workspace graph
  5. returns a dry-run plan or commits the new version and optionally waits for the apply job

ff apply is graph-wide. It does not patch one object at a time.

Example Apply File

from datetime import timedelta

import featureform as ff
from featureform.types.resource import FeatureView, MaterializationEngine, TrainingSetType

postgres = ff.get_postgres("analytics-postgres")

customer = ff.Entity(
    name="customer",
    description="Customer entity for fraud models",
)

transactions = postgres.dataset(
    name="transactions",
    schema="public",
    table="transactions",
    timestamp_column="event_ts",
    description="Raw payment events",
)


@postgres.sql_transformation(
    name="customer_daily_rollups",
    description="Daily transaction totals per customer",
    inputs=[transactions],
)
def customer_daily_rollups() -> str:
    return """
        SELECT
            customer_id,
            date_trunc('day', event_ts) AS event_day,
            SUM(amount) AS total_amount,
            COUNT(*) AS transaction_count
        FROM {{transactions}}
        GROUP BY 1, 2
    """


customer_amount_7d = (
    ff.Feature(name="customer_amount_7d")
    .from_dataset(
        customer_daily_rollups,
        entity="customer",
        entity_column="customer_id",
        value="total_amount",
        timestamp="event_day",
    )
    .with_provider("analytics-postgres")
    .aggregate(function=ff.AggregateFunction.SUM, window=timedelta(days=7))
)

fraud_label = (
    ff.Label()
    .from_dataset(transactions)
    .value("is_fraud")
    .timestamp("event_ts")
    .entity("customer", column="customer_id")
    .build()
)

fraud_training = ff.TrainingSet(
    name="fraud_training",
    provider="analytics-postgres",
    features=[customer_amount_7d],
    label=fraud_label,
    type=TrainingSetType.STATIC,
)

customer_features = FeatureView(
    name="customer_features",
    entity="customer",
    features=[customer_amount_7d.name],
    inference_store="online-store",
    materialization_engine=MaterializationEngine.K8S,
)

resources = [
    customer,
    transactions,
    customer_daily_rollups,
    customer_amount_7d,
    fraud_label,
    fraud_training,
    customer_features,
]

Apply Strategies And Execution Modes

Redis Feature Form now exposes apply strategy and execution mode as separate axes.

Apply strategies:

  • APPLY strategy: submitted resources replace the desired graph for the workspace
  • MERGE strategy: submitted resources merge into the workspace and omitted resources are retained

Execution modes:

  • NORMAL: standard diff-based planning
  • UPDATE: revisit the target graph in update mode
  • FULL_REMATERIALIZE: revisit the target graph in full-rematerialize mode

That means combinations such as these are valid:

  • APPLY + NORMAL
  • APPLY + UPDATE
  • APPLY + FULL_REMATERIALIZE
  • MERGE + NORMAL
  • MERGE + UPDATE
  • MERGE + FULL_REMATERIALIZE

Apply From The CLI

Preview the graph delta without changing the workspace:

ff --server grpc.example.com:443 --transport grpc \
  apply -f resources.py --workspace fraud-detection --plan

Apply the submitted graph and wait for completion:

ff --server grpc.example.com:443 --transport grpc \
  apply -f resources.py \
  --workspace fraud-detection \
  --message "initial fraud pipeline" \
  --wait --wait-for finished

Merge into the existing workspace instead of replacing omitted resources:

ff --server grpc.example.com:443 --transport grpc \
  apply -f resources.py \
  --workspace fraud-detection \
  --merge \
  --wait --wait-for finished

Run a plan in update mode:

ff --server grpc.example.com:443 --transport grpc \
  apply -f resources.py \
  --workspace fraud-detection \
  --plan \
  --update

Request a merge with full rematerialization semantics:

ff --server grpc.example.com:443 --transport grpc \
  apply -f resources.py \
  --workspace fraud-detection \
  --merge \
  --full-rematerialize

Useful flags:

  • --plan: show what would change without applying
  • --merge: keep omitted resources already present in the workspace
  • --update: use update execution mode
  • --full-rematerialize: use full rematerialization execution mode
  • --wait --wait-for finished: block until the apply job completes and the workspace version is visible

Apply From Python

Use client.apply() for standard apply semantics:

import os

import featureform as ff
import resources

client = ff.Client(
    base_url="grpc.example.com:443",
    transport="grpc",
    token=os.environ["FEATUREFORM_TOKEN"],
)

result = client.apply(
    resources=resources.resources,
    workspace="fraud-detection",
    message="initial fraud pipeline",
    wait=True,
)

print(result.version)
for change in result.changes:
    print(change.resource_type, change.resource_name, change.action)

Use execution mode directly from Python:

plan = client.apply(
    resources=resources.resources,
    workspace="fraud-detection",
    dry_run=True,
    execution_mode="UPDATE",
)

Use merge semantics without deleting omitted resources:

result = client.merge(
    resources=resources.resources,
    workspace="fraud-detection",
    execution_mode="FULL_REMATERIALIZE",
    wait=True,
)

If resources is omitted, client.apply(...) and client.merge(...) use the global resource registry. That works well when definition modules register resources during import.

Query Offline Data

Use Arrow Flight helpers to pull datasets, training sets, or feature-view snapshots into pandas or stream them incrementally.

training = client.query_training_set(
    "fraud_training",
    workspace="fraud-detection",
    flight_server="grpc.example.com:9090",
).to_pandas()

print(training.head())

You can also query datasets directly:

transactions = client.query_dataset(
    "transactions",
    workspace="fraud-detection",
    limit=1000,
).to_pandas()

Serve Online Features From Redis

Once a feature view is materialized, Redis Feature Form serves online values from Redis with client.serve(...).

features = client.serve(
    "customer_features",
    entity="customer_123",
    workspace="fraud-detection",
)

print(features["customer_amount_7d"])

Batch serving is supported as well:

result = client.serve(
    "customer_features",
    entities=["customer_123", "customer_456"],
    workspace="fraud-detection",
    return_type="pandas",
)

Package Surface

  • featureform.Client: client for workspaces, providers, apply and merge, offline queries, and online serving
  • ff: CLI for auth, apply, workspace, provider, catalog, graph, scheduler, and RBAC operations
  • featureform.resources: typed resource DSL for authoring Redis Feature Form resource graphs
  • featureform.types: request and response models used by the client surface

Engineering Documentation

Use CLI Getting Started for ff endpoint, transport, authentication, and output behavior, and Applying Resource Definitions for plan/apply semantics. The repository engineering docs cover system architecture, resource/provider contracts, serving, examples, and server-state boundaries. This README remains the package entrypoint for installing and using the Python client.

Metadata

Release files for redis-featureform 3.3.0rc1

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

Source distribution (sdist)

Source distribution for redis-featureform 3.3.0rc1
File Size Uploaded
redis_featureform-3.3.0rc1.tar.gz 463.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for redis-featureform 3.3.0rc1
File Interpreter ABI Platform
redis_featureform-3.3.0rc1-py3-none-any.whl Python 3 none any Details

Total release size: 1.0 MB

Release files / redis_featureform-3.3.0rc1.tar.gz

Download URL redis_featureform-3.3.0rc1.tar.gz
Size 463.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3a0a354ca33b154b17757072f52153d0e37f33eb6520fdfb97cb9c550d96f491
BLAKE2b-256 checksum
How to use checksums
8f2dcf27478d5323ce286061bca2a01207c45f1aa723de8d0f0c608e13ac91dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / redis_featureform-3.3.0rc1-py3-none-any.whl

Download URL redis_featureform-3.3.0rc1-py3-none-any.whl
Size 551.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
896857687f388ad5b8e55644bf65149e2be4e1e9569c196cc27cd6b0e945e4ef
BLAKE2b-256 checksum
How to use checksums
eb88f036c555390a8effd969d174d05eb067a00a723f4dc742db7de87bb81889
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14
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