SageMaker Feature Store: BatchWriteRecord & ListRecords reduce API churn and expose in-memory keys

Batch write and discover records in Amazon SageMaker Feature Store

If your feature ingestion pipeline makes thousands of PutRecord calls per second, two new SageMaker Feature Store APIs, BatchWriteRecord and ListRecords, change the operational calculus. Announced in July 2026 by Harshil Shah, Dhaval Shah, Chirag Pandey, and Siamak Nariman, these data-plane additions cut connection overhead for high-throughput ingestion and finally give teams a way to enumerate records in Redis-backed (In‑Memory) feature groups.

The short story

PutRecord writes one record to a single feature group per call and uses EventTime-based conditional semantics. BatchWriteRecord accepts up to 25 entries per request across one or more feature groups. It reports per-entry success or failure, supports per-entry TTL, and preserves the same EventTime-based ordering semantics as PutRecord. ListRecords paginates active record identifiers in a feature group and works with both the Standard (DynamoDB-backed) and In‑Memory (Redis-backed) tiers.

For reference, see the Amazon What’s New announcements and the SageMaker API documentation for the authoritative details: the AWS What’s New hub and the Amazon SageMaker API Reference.

Why this matters

  • Reduce API call churn. A pipeline that once made N PutRecord calls can cut request count by up to 25× by batching up to 25 entries per BatchWriteRecord request (the announcement cites this reduction).
  • Preserve correctness. BatchWriteRecord uses the same EventTime-based conditional-write semantics as PutRecord: “If the incoming record’s EventTime is newer than the existing record, it becomes the latest version in the online store.”
  • Discover and manage in-memory data. ListRecords fills a long-standing gap for In‑Memory tier feature groups. Previously, “There is no offline store for the In‑Memory tier to fall back on, no Amazon Athena query to run, and no API to discover what exists.”

Practical facts, what these APIs do

  • BatchWriteRecord
    • Accepts up to 25 entries per request. Entries may target one or more feature groups in the same call.
    • Per-entry TargetStores: each entry can target OnlineStore, OfflineStore, or both.
    • Preserves EventTime-based ordering semantics like PutRecord. “If the incoming record’s EventTime is newer than the existing record, it becomes the latest version in the online store.”
    • Partial-success model. The response includes per-entry Errors and an UnprocessedEntries field listing items to retry. The API does not roll back successful writes.
    • Per-entry TTL. Include TtlDuration on individual entries. Example JSON for a seven-day TTL: {“Unit”:”Days”, “Value”:7}.
    • Permissions: callers must have sagemaker:BatchWriteRecord and sagemaker:PutRecord on the ARN of each target feature group. Authorization is checked per feature group.
  • ListRecords
    • Enumerates active (non-deleted, non-expired) record identifiers in a feature group with pagination.
    • Works with Standard (DynamoDB) and In‑Memory (Redis) online-store tiers.
    • Returns identifiers only. Use GetRecord or BatchGetRecord to fetch feature values.
    • Pagination: MaxResults defaults to 10 and can be set up to 100. NextToken is an opaque, account- and feature-group-scoped token. Results are not returned in a guaranteed order, and concurrent writes during pagination can produce duplicates or gaps.
    • Permissions: callers need sagemaker:ListRecords on the feature group ARN.

TTL precedence (exact order)

When multiple TTLs could apply, SageMaker resolves them in this order:

  • Record-level TTL, set with TtlDuration on individual entries. Takes highest priority.
  • Request-level TTL, a default TtlDuration at the top level of the request, applied to entries without a record-level TTL.
  • Feature-group-level TTL, the TTL configured on the feature group itself, applied when neither record-level nor request-level TTL is set.

Operational guidance, how to use these APIs well

  • Batch selectively, not blindly. Aim for larger batches (for example, 16-25) to reduce connection count, but test the tradeoff between batch size and end-to-end latency for your use case.
  • Group by feature group when possible. Mixing many feature groups in a single batch increases the blast radius of a transient failure and makes retries harder. Batching by target feature group simplifies error handling.
  • Implement selective retry with jittered exponential backoff. Retry only entries returned in Errors or UnprocessedEntries. Do not resend successful entries to avoid duplicates and amplification.
  • Watch EventTime semantics in a batch. EventTime-based conditional writes still govern which record becomes the online “latest.” Include tests that exercise intra-batch writes to the same record identifier with different EventTimes.
  • Don’t assume immediate offline-store availability. The OfflineStore (S3 plus Glue catalog) is eventually consistent for historical versions. Validate availability timelines for downstream training jobs.
  • Validate quotas and tail latency. BatchWriteRecord lowers request count but overall throughput still depends on account-level quotas, per-feature-group limits, and the backing store (DynamoDB or Redis). Run load tests and request quota increases if needed.
  • Clean In‑Memory data before deleting feature groups. Use ListRecords to enumerate keys and DeleteRecord to remove them, otherwise memory-backed entries can become orphaned in ElastiCache.
  • Costs. Fewer requests does not automatically mean a lower bill. Confirm request and storage pricing for Feature Store in your account and check any changes in egress, storage, or per-request charges.

Minimal IAM examples (illustrative)

The announcement shows a concise data-plane example. An illustrative minimal inline policy that grants the data-plane calls across feature groups looks like:

  • {
    “Version”: “2012-10-17”,
    “Statement”: [
    {
    “Effect”: “Allow”,
    “Action”: [
    “sagemaker:BatchWriteRecord”,
    “sagemaker:PutRecord”,
    “sagemaker:ListRecords”
    ],
    “Resource”: “arn:aws:sagemaker:*:*:feature-group/*”
    }
    ]
    }

For production, do not use a wildcard Resource. A least-privilege example for a single feature group might specify:

  • “Resource”: “arn:aws:sagemaker:us-east-1:123456789012:feature-group/my-feature-group”

Or use role assumption patterns to avoid wide-scoped cross-account permissions.

Recommended tests and playbook (practical validation before you adopt)

Run these tests in a staging environment and capture assertions so you can rely on the APIs in production.

  • Intra-batch ordering: Send a single BatchWriteRecord with multiple writes to the same recordId using different EventTime values. Assert the online store reflects the record with the newest EventTime as the “latest” and the offline store contains historical versions where configured.
  • Partial-failure behavior: Craft a batch with one entry that violates schema or permissions and confirm which entries succeed, what the Errors and UnprocessedEntries fields contain, and that successful writes are not rolled back.
  • ListRecords pagination under load: Paginate a feature group while performing concurrent writes and deletes. Observe duplicates or gaps and measure p95/p99 latencies. Verify NextToken behavior across retries.
  • TTL precedence verification: Write entries with conflicting TTLs (record-level, request-level default, and feature-group default) and confirm expiry follows the Record-level > Request-level > Feature-group-level order.
  • Throughput & connection-count comparison: Compare a PutRecord-only ingestion pipeline with a BatchWriteRecord pipeline for equivalent event throughput. Measure socket counts, CPU, latency tail, and error rates.

Simple retry playbook (pseudocode)

  • Call BatchWriteRecord with up to 25 entries.
  • Inspect response and collect IDs from Errors and UnprocessedEntries.
  • If any entries need retry, add randomized jitter and backoff, then retry only those entries. Cap total retries to avoid repeated amplification.
  • Log successes and failures per entry for audit and debugging. Persist any unresolvable failures for manual review.

Practical workflows enabled

  • High-throughput ingestion: BatchWriteRecord reduces per-record connection churn, lowering client socket usage and making it easier to sustain tens of thousands of events per second with fewer client connections.
  • Orphan cleanup for In‑Memory stores: ListRecords plus DeleteRecord gives a safe path to enumerate and remove expired or orphaned keys before deprovisioning feature groups.
  • Compliance and audit automation: Use ListRecords to enumerate subject identifiers, then combine selective deletes and audit-record writes (to S3 or an audit feature group) to demonstrate lifecycle actions.

Caveats and open questions to validate in your environment

  • Service-side throughput quotas, per-account throttling, and p99 latency characteristics for BatchWriteRecord are not specified in the announcement. Run load tests and engage AWS support for quota increases.
  • Behavior when a single BatchWriteRecord request contains multiple entries for the same record identifier with different EventTimes should be exercised by your tests to confirm intra-request resolution matches expectations.
  • ListRecords returns identifiers only. If you require timestamps, TTLs, or other metadata alongside identifiers, plan a small metadata index in your own system or follow up with GetRecord/BatchGetRecord after enumeration.
  • For compliance, deletion from Feature Store may be necessary but not sufficient for regulatory proof-of-deletion. Preserve audit logs and consider immutable audit trails in S3 or a centralized logging system.

Prerequisites

  • An AWS account with permissions to create SageMaker resources and an execution role with access to Amazon S3 and AWS Glue where applicable.
  • Boto3 (use the latest published version) or the SageMaker Python SDK (the announcement references SageMaker Python SDK v3.8.0 or later as a minimum supported level in examples).
  • One or more existing feature groups with records ingested; the announcement links to example notebooks and an end-to-end workshop for hands-on guidance.

Key takeaways, quick Q&A

  • How many entries can I write per BatchWriteRecord request?

    Up to 25 entries per request; entries may target one or more feature groups.

  • Does BatchWriteRecord preserve EventTime ordering?

    Yes. According to the announcement, it preserves the same EventTime-based conditional-write semantics as PutRecord: only newer EventTime records become the online “latest, ” otherwise the data becomes a historical version in the offline store (when present).

  • How are TTLs resolved when multiple levels exist?

    Record-level TTL (TtlDuration on an entry) has top priority, then a request-level TtlDuration, and finally the feature-group-level TTL if neither is set.

  • Can I list records in In‑Memory (Redis) feature groups?

    Yes. ListRecords supports both the Standard (DynamoDB) and In‑Memory (Redis) online-store tiers and returns active identifiers via pagination.

  • What permissions do I need?

    Callers need sagemaker:BatchWriteRecord and sagemaker:PutRecord for writes and sagemaker:ListRecords to enumerate; permissions are checked per feature-group ARN.

“BatchWriteRecord and ListRecords provide key enhancements in the data plane of Amazon SageMaker Feature Store. BatchWriteRecord reduces the API call volume for high-throughput ingestion by up to 25x while preserving the EventTime-based ordering guarantees that keep your online store correct. ListRecords unlocks record discovery and lifecycle management. This is critical for In-Memory tier customers who previously had no way to enumerate or clean up their data.”

The announcement (July 2026) was authored by Harshil Shah, Dhaval Shah, Chirag Pandey, and Siamak Nariman. Treat BatchWriteRecord and ListRecords as powerful primitives: they lower operational friction, but real-world benefits require testing for quotas, latency, and concurrency edge cases. Run the suggested validation playbook, adopt selective retry patterns, and re-run your ingestion benchmarks, you’ll likely find fewer sockets, fewer API calls, and cleaner operational workflows as a result.