Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a820f4e
create new files in develop/ai
kaitlynmichael May 12, 2026
935f357
typo
kaitlynmichael May 12, 2026
53b3e06
DOC-6581 DOC-6582
kaitlynmichael May 12, 2026
e3c16af
DOC-6583
kaitlynmichael May 12, 2026
734b8ed
indent list
kaitlynmichael May 12, 2026
cc4899b
review feedback
kaitlynmichael May 14, 2026
12a7a2e
DOC-6588
kaitlynmichael May 27, 2026
5eccecd
concepts rough draft
kaitlynmichael May 27, 2026
31edbcd
intro and how the pieces fit together
kaitlynmichael May 27, 2026
7ef2ddc
concepts edits
kaitlynmichael May 27, 2026
f9eeec8
manage workspaces DOC-6583
kaitlynmichael May 27, 2026
fe037d4
auth rough draft DOC-6590
kaitlynmichael May 27, 2026
79a018d
auth changes
kaitlynmichael May 28, 2026
49752f7
remove old pages
kaitlynmichael Jun 16, 2026
2905db8
define and deploy features
kaitlynmichael Jun 16, 2026
4983779
aliases and links
kaitlynmichael Jun 16, 2026
8d13679
ai drafts
kaitlynmichael Jun 17, 2026
90aedbd
SME feedback
kaitlynmichael Jun 17, 2026
4f25799
reference page editorial review
kaitlynmichael Jun 17, 2026
85a41c5
quickstart edits
kaitlynmichael Jun 23, 2026
13682f9
DOC-6788 edits
kaitlynmichael Jun 25, 2026
7051960
Merge branch 'main' into DOC-6576
kaitlynmichael Jun 25, 2026
92c44e0
assess-comments coverage ledger: +#3312 evidence
kaitlynmichael Jun 25, 2026
89993f1
feedback edits
kaitlynmichael Jun 25, 2026
6452f7e
deploy first pass edit
kaitlynmichael Jun 25, 2026
199fc9d
editorial pass deploy page
kaitlynmichael Jun 25, 2026
c4f9467
clarifying edits for auth page
kaitlynmichael Jun 25, 2026
9b33d99
oprate/index editorial
kaitlynmichael Jun 25, 2026
4f1fb52
Merge remote-tracking branch 'origin/main' into DOC-6576
kaitlynmichael Jul 23, 2026
3f1c778
cleanup edits
kaitlynmichael Jul 23, 2026
3fc0ce8
clean up edits
kaitlynmichael Jul 23, 2026
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
14 changes: 14 additions & 0 deletions .claude/state/assess-comments.coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,20 @@ rule fires and distinguishes fixed from still-broken.
("Wrong FT.INFO document count field", inline, 06-17) independently flagged
the same `info.numDocs` → `num_docs` bug. Verified fixed in current code.

### Approval-over-open-finding — benign variants

- **#3312 dwdougherty, 2026-05-12.** Review state `COMMENTED` (not `APPROVED`)
with body *"Apart from the issues already identified by Bugbot, LGTM."* sat
over 3 open bugbot findings. **Explicit carveout** — the human deliberately
excluded the bot's findings from the LGTM. Over the following months, 1
finding (3228632453 raw-md → relref) was substantively fixed by the author and
2 (3228632434 streaming.md empty page; 3228632444 manage-workspace.md empty
frontmatter) became *stale via the broader restructure* (streaming.md
deleted; manage-workspace.md fully populated with frontmatter). Pattern: the
approval-over-open-finding signal *did* fire, but the carveout language made
it benign and the open findings were later defanged by unrelated work. Distinct
from the dangerous variant where an "LGTM" silently rides over a real bug.

### Bot false positives (calibration signatures)
- **#3604 async fire-on-call mis-modeled, 2026-07-08 (first adjudicated bugbot FP).**
Bugbot raised two Medium concurrency findings on new Lettuce doc examples, same
Expand Down
199 changes: 199 additions & 0 deletions content/develop/ai/featureform/concepts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
---
title: Redis Feature Form concepts
description: Learn the workspace, resource graph, provider, secret, and serving model behind Redis Feature Form.
linkTitle: Concepts
weight: 30
aliases:
- /develop/ai/featureform/training-sets-and-feature-views/
---

Redis Feature Form is a feature platform. It turns raw data from your existing systems into the values your models read at inference time. This page introduces the core concepts behind that workflow.

## How the pieces fit together

A Feature Form deployment runs one or more [workspaces](#workspaces). Each workspace owns a versioned [resource graph](#the-resource-graph) that describes what features should exist, where their inputs live, and how they're served. You author that graph in a Python [definitions file](#definitions-files-and-ff-apply) and apply it with `ff apply`. The `ff` command-line tool also handles workspaces, providers, RBAC, and serving operations.

The graph itself is data, not credentials or connections. [Providers](#providers) connect the workspace to external systems (Postgres, Redis, S3, Spark, an Iceberg catalog), and [secret references](#secrets-and-secret-references) point to the backend that holds the credentials. At the end of the chain, a [feature view](#feature-views-and-serving) is the single resource the rest of your stack reads from to serve features online.

## Workspaces

A workspace is a self-contained environment in Feature Form. Each one owns its own resource graph, providers, secret references, and serving metadata. Nothing is shared between workspaces.

Use workspaces to keep environments such as dev, staging, and prod separate, or to give independent teams their own area on a shared deployment. Conceptually, a workspace is a single tenant in a multi-tenant Feature Form deployment — providers, secret references, RBAC bindings, and graph state are all scoped per workspace, even though they share the underlying server. Two workspaces can connect to the same external Postgres database and remain fully isolated, because each workspace tracks its own resources.

Every workspace also has a `last_applied_version` counter that increases each time you successfully apply a change. Read commands always return the latest committed version.

To create, inspect, update, or delete workspaces, see [Manage workspaces]({{< relref "/develop/ai/featureform/manage-workspace" >}}).

## The resource graph

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.

You decide if you think it's necessary to mention this at the concepts level, but it might be helpful to explain that Feature Form's planner converts the resource graph—which is a logical, declarative representation of a workspace's feature engineering pipeline—into a task DAG that is executed by Feature Form such that the actual state of the workspace is reflected in the users' data infrastructure (e.g. Snowflake).

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.

There's also the Feature Form catalog to mention on this point: it shows where logical resources (e.g. datasets) exist as physical tables in providers (e.g. Snowflake (offline provider) and/or Redis (online provider).

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.

Good addition — deferring to Phase 2 (concepts deepening / reference normalization), since it expands the concept model beyond Phase 1's mechanical restructure. Tracked there.


The resource graph describes what a workspace should look like. Every feature, label, transformation, dataset, and feature view lives in this graph and refers to the others by name.

Two properties shape how you work with it:

- It is versioned as a whole. Each successful change creates a new version of the entire graph. Either every resource in the change lands together, or nothing does — you never end up with half-applied feature definitions.
- It is declarative. You describe what the graph should look like, not the steps to get there. Feature Form figures out the difference between the current graph and the new one and applies only what changed.

When `ff apply` accepts a change, Feature Form's planner converts the desired graph into a task DAG that runs against your data infrastructure — materializing new datasets, executing transformations, and populating the online store. The graph is the logical specification; the task DAG is the executed plan.

### Resource types

A graph is built from seven resource types. New users encountering Feature Form for the first time benefit from learning these as a vocabulary list — every other concept on this page builds on them.

- **Entities** identify the real-world objects features describe, such as a `customer` or `order`. Other resources join on the entity's primary key — the actual column name can vary across tables (`customer_id`, `user_id`, `id`), as long as the values identify the same business entity.
- **Datasets** point at an existing table, view, or file in an offline store and make it visible to the graph. The data itself stays where it lives; Feature Form just registers a handle to it.
- **Transformations** produce new datasets from existing ones, expressed as SQL or as a Spark job. A transformation describes the shape of the output; the compute that runs it is supplied by a provider.
Comment thread
kaitlynmichael marked this conversation as resolved.
- **Features** are named, measurable characteristics of an entity that a model reads as input at inference time. A feature attaches to a column of a dataset (or transformation), optionally applies an aggregation (such as `SUM` over a 7-day window), and declares which provider owns its computation.
- **Labels** are the target value a model is trained to predict — the known outcome attached to each training example. They share the entity-keyed shape of features but feed offline training rather than online serving.
- **Training sets** join one or more features with a label by entity key and time, so an offline training job reads a single point-in-time-correct table instead of stitching inputs together by hand. The point-in-time alignment prevents data leakage — features whose values weren't actually known at the label's timestamp.
- **Feature views** group related features for an entity behind a shared definition, materialization policy, and serving contract. They're the primary interface model-serving systems use to read feature values at inference time, and the only graph resource downstream applications interact with directly.

The following example definitions file shows how the vocabulary above appears as code.
Comment thread
kaitlynmichael marked this conversation as resolved.

```python
import featureform as ff
from datetime import timedelta

customer = ff.Entity(name="customer") # Entity: the real-world object features describe

transactions = postgres.dataset( # Dataset: registers an existing table with the graph
name="transactions_raw",
table="transactions",
timestamp_column="timestamp",
)

# Transformation: derives a new dataset from existing ones via SQL
@postgres.sql_transformation(name="customer_daily_rollups", inputs=[transactions])
def customer_daily_rollups() -> str:
return """
SELECT customer_id,
date_trunc('day', timestamp) AS event_day,
SUM(transaction_amount) AS total_amount
FROM {{transactions_raw}}
GROUP BY 1, 2
"""

# Feature: an aggregated value served to models at inference time
customer_total_amount_7d = (
ff.Feature(name="customer_total_amount_7d")
.from_dataset(customer_daily_rollups, entity="customer",
entity_column="customer_id", value="total_amount",
timestamp="event_day")
.aggregate(function=ff.AggregateFunction.SUM, window=timedelta(days=7))
)

customer_risk_view = ff.FeatureView( # Feature view: groups features behind a serving contract
name="customer_risk_feature_view",
entity="customer",
features=[customer_total_amount_7d],
inference_store="demo_redis",
)
```

### Definitions files and `ff apply` {#definitions-files-and-ff-apply}
Comment thread
kaitlynmichael marked this conversation as resolved.

The Python definitions file is the source of truth for what the graph should look like. The file uses Python to declare resources, not to run commands against Feature Form. When you run `ff apply`, Feature Form imports the file, collects those resources, and treats them as the workspace's desired state. Feature Form compares that set with the current graph and, if the change is accepted, commits a new graph version.

By default, `ff apply` replaces the workspace's current graph with the resources defined in the file. Any existing resource not in the file becomes a candidate for removal. To apply a partial set and leave missing resources untouched, run `ff apply --merge` instead.

{{< note >}}
Definitions files describe features, not infrastructure. Providers and secret backends are registered separately by a workspace admin. Definitions files reference providers by name and assume they already exist. This separation keeps feature authors away from credentials and infrastructure choices.
{{< /note >}}

For an end-to-end walkthrough of authoring a definitions file and applying it, see the [Quickstart]({{< relref "/develop/ai/featureform/quickstart" >}}). For the full apply lifecycle and editing loop, see [Define and deploy features]({{< relref "/develop/ai/featureform/define-and-deploy-features" >}}) and [Update features]({{< relref "/develop/ai/featureform/update-features" >}}).

## Secrets and secret references

Feature Form never stores credentials in any form — not plaintext, not hashed, not encrypted. A provider configuration carries a secret reference that points at a separately-registered secret backend, and Feature Form resolves the reference at the moment the credential is needed. Because of this, secret providers are registered first — every provider that follows points back at one through its secret reference.

Keeping credentials out of the graph has two important consequences:

- The graph is safe to inspect and export. Nothing in it contains a usable credential. You can hand the graph to another team, version it, or paste it into a ticket without leaking secrets.
- The process that resolves a reference is whichever process actually needs the credential. In a deployed environment, that's almost always the Feature Form server, not your local CLI shell. A reference such as `env:PG_PASSWORD` reads from the server's process environment, not yours.

Every new workspace is created with a built-in `env` secret provider, which makes `env:` references work out of the box for local development. Production deployments typically register a Vault, Kubernetes-secrets, or AWS Secrets Manager backend instead, because the `env` backend offers no rotation, no audit, and exposes values in process listings.

To register a secret provider for a workspace, see [Configure secret providers]({{< relref "/develop/ai/featureform/register-providers#configure-secret-providers" >}}).

## Providers

A provider is the workspace's connection to an external system. It carries the host, port, credentials reference, and any configuration Feature Form needs to talk to that system. Resources in the graph reference providers by name, so you must register a provider in the workspace before applying any resource that uses it.

Every provider fills one or more roles, which describe the kind of work it can do for the workspace:

| Role | What it does |
| --------------- | ----------------------------------------------------------------------- |
| `offline-store` | Holds batch data and materialized datasets the graph reads from. |
| `online-store` | Serves materialized feature values to applications at low latency. |
| `compute` | Runs transformations and materialization jobs. |
| `streaming` | Connects the workspace to streaming sources. |

One provider often fills more than one role. Postgres, for example, is commonly registered as both `offline-store` and `compute` because the same instance that holds datasets can run SQL transformations against them. The documented integrations and their typical roles:

| Provider | Typical roles |
| ----------------- | ------------------------------ |
| Postgres | `offline-store`, `compute` |
| Redis | `online-store` |
| S3 | `offline-store` |
| Spark | `compute` |
| Iceberg catalog | `offline-store` |

The role model is what lets a graph stay portable: a feature definition doesn't care that compute happens to be Postgres in dev and Spark in prod, only that some provider fills the `compute` role.

To register providers in a workspace, see [Register providers]({{< relref "/develop/ai/featureform/register-providers" >}}).

## Feature views and serving

A feature view is the resource that everything else in the graph eventually feeds. Applications query it to get the latest features for an entity.

A feature view declares:

- The entity used as the lookup key (for example, `customer`).
- The list of features it exposes.
- The online provider that holds the materialized values — typically Redis.
- A materialization engine that produces those values from offline data.

For example:

```python
customer_risk_view = ff.FeatureView(
name="customer_risk_feature_view",
entity="customer",
features=[customer_total_amount_7d, customer_transaction_count_7d],
inference_store="demo_redis",
)
```

### Feature view requirements

Before applications can read from a feature view:

- The online provider it points to must be registered and reachable.
- The graph version that introduced the feature view must be committed.
- Materialization must have populated values for the entities you want to query.

If any of those are missing, the read fails immediately rather than returning stale data.

### Serving interfaces

Applications can read feature values through any of three interfaces:

- A gRPC service (`ServingService.Serve` and `ServingService.GetServingMetadata`).
- A REST endpoint (`POST /api/v1/serve`).
- A Python client (`client.serve(...)`).

{{< note >}}
Reading feature values and reading serving metadata are governed by separate RBAC permissions. For example, a dashboard user can have access to feature view schemas without access to the actual values — or vice versa.
{{< /note >}}

To serve from a feature view in an application, see [Serve features]({{< relref "/develop/ai/featureform/serve-features" >}}). To inspect datasets, training sets, or feature views directly, see [Query data]({{< relref "/develop/ai/featureform/query-data" >}}).

## Next steps

- [Quickstart]({{< relref "/develop/ai/featureform/quickstart" >}}) — one end-to-end walkthrough that exercises every concept on this page.
- [Manage workspaces]({{< relref "/develop/ai/featureform/manage-workspace" >}}) — create, inspect, update, and delete workspaces.
- [Register providers]({{< relref "/develop/ai/featureform/register-providers" >}}) — connect the workspace to Postgres, Redis, S3, Spark, or an Iceberg catalog, and register secret backends.
- [Define and deploy features]({{< relref "/develop/ai/featureform/define-and-deploy-features" >}}) — author a definitions file and run `ff apply`.
- [Update features]({{< relref "/develop/ai/featureform/update-features" >}}) — iterate on a graph after the first apply.
- [Serve features]({{< relref "/develop/ai/featureform/serve-features" >}}) — read from a feature view in an application.
- [Query data]({{< relref "/develop/ai/featureform/query-data" >}}) — inspect datasets, training sets, and feature views directly.
Loading
Loading