Amazon Web Services has added two new data-plane APIs to Amazon SageMaker Feature Store: BatchWriteRecord and ListRecords. Announced August 28, 2026 in a post by AWS Senior Solutions Architects Harshil Shah and Dhaval Shah, software engineer Chirag Pandey, and Senior Product Manager Siamak Nariman, the update lets machine learning teams batch write records across multiple feature groups in a single call and discover which records already exist in a feature group, instead of relying on single-record calls and known identifiers.
The change targets two specific operational gaps AWS says show up repeatedly in production ML pipelines. High-throughput ingestion jobs previously had to call the existing PutRecord API once per record per feature group, and teams using Feature Store’s In-Memory storage tier had no way to enumerate or recover records if identifiers were lost. BatchWriteRecord and ListRecords are built directly into the SageMaker Feature Store Runtime API and are available now through Boto3 and the SageMaker Python SDK.
What BatchWriteRecord and ListRecords Actually Do
Amazon SageMaker Feature Store is AWS’s managed repository for storing and serving machine learning features, combining a low-latency online store for real-time inference with an offline store for historical training data. Until this update, writing to it meant calling PutRecord once per record, and there was no API to list what a feature group actually contained.
The two new APIs close those gaps:
- BatchWriteRecord writes up to 25 records across one or more feature groups in a single request, with partial-success semantics, per-record time-to-live (TTL) control, and the same EventTime-based ordering guarantees as PutRecord.
- ListRecords enumerates record identifiers within a feature group using pagination, and works with both the Standard tier (backed by Amazon DynamoDB) and the In-Memory tier (backed by Amazon ElastiCache for Redis).
Why Single-Record Writes Became a Bottleneck
Before this release, every write to Feature Store went through PutRecord, which persists one record to one feature group per call using a conditional write: a record only becomes the “latest” version if its EventTime is newer than what’s already stored. That design gives strong ordering guarantees, but it forces an N-records-by-M-feature-groups calling pattern at scale. A pipeline writing to several feature groups at once had to open a proportional number of individual connections, adding overhead and tail latency that capped overall throughput. BatchWriteRecord collapses that pattern into a single call that can span multiple feature groups at once, and because each entry succeeds or fails independently, one bad record doesn’t block the other 24 in the batch.
The Record-Discovery Gap ListRecords Closes
The second gap was arguably more serious for compliance-sensitive teams. Feature Store already supported PutRecord, GetRecord, and DeleteRecord, but all three require the caller to already know the exact record identifier. For the Standard tier, teams could work around this by querying the offline store through Amazon Athena, but that adds cost, requires offline store configuration, and isn’t real-time. For the In-Memory tier there was no workaround at all: there is no offline store fallback, so a lost record identifier meant the record became permanently unrecoverable, undeletable, and invisible a real problem for teams that need to prove they’ve deleted a user’s data on request. ListRecords returns only active, non-deleted, non-expired identifiers, scanning DynamoDB for the Standard tier or filtering Redis keys for the In-Memory tier.
How the Two APIs Work Together
AWS’s own example in the announcement is a data-deletion workflow: use ListRecords to enumerate a user’s records across every feature group that might hold them, call DeleteRecord on each match, then use BatchWriteRecord to write a single audit-log entry confirming the deletion completed. That combination discover, delete, log is the kind of compliance pattern that was previously difficult to build against the In-Memory tier specifically, since there was no reliable way to confirm a record existed before trying to remove it.
Request Structure and Key Limits
A BatchWriteRecord call takes a list of entries, each specifying a FeatureGroupName, the record’s feature values, which stores to target (OnlineStore, OfflineStore, or both), and an optional TTL. The response only lists what failed: entries not present in Errors or UnprocessedEntries succeeded, and AWS recommends retrying only the failed entries with exponential backoff. TTL is resolved in a defined order of precedence a TTL set on an individual record wins, then a request-level default, then whatever TTL is configured on the feature group itself.
ListRecords pagination defaults to 10 results per page with a maximum of 100, using an opaque token that’s tied to a specific feature group and account. AWS notes that result ordering isn’t guaranteed and that concurrent writes during pagination can produce duplicates or gaps in the results documented behavior rather than a bug.
Getting Started
Both APIs ship in the current version of Boto3 and in SageMaker Python SDK v3.8.0 and later. A caller needs sagemaker:BatchWriteRecord and sagemaker:ListRecords permissions on the target feature group ARNs, checked per feature group before any records are processed. In practice, a batch write call looks like passing a list of entries each with its own feature group name, feature values, and target stores to the batch_write_record client method, and checking the returned Errors and UnprocessedEntries lists to decide what to retry. Enumerating a feature group is a simple pagination loop: call list_records with a FeatureGroupName and MaxResults, collect the RecordIdentifiers, and keep following the NextToken until it’s absent from the response.
How This Compares to the Old Workflow
This update is specific to SageMaker Feature Store’s own record APIs rather than a change to Amazon DynamoDB’s BatchWriteItem, which is a separate AWS service with its own 25-item-per-call limit and its own retry semantics for unprocessed items a distinction worth noting since the two are easy to conflate given the similar batching model. Teams evaluating either service for high-throughput ingestion, including those already comparing MCP-based observability tooling for agentic pipelines or Amazon Connect-based agent deployments, will find the batching and pagination patterns broadly familiar.
What AWS Didn’t Change
The current release of ListRecords returns record identifiers only, not the underlying feature values retrieving those still requires a follow-up GetRecord or BatchGetRecord call. BatchWriteRecord also doesn’t roll back successful writes if other records in the same batch fail; it’s explicitly a partial-success API, not a transactional one, so retry logic has to target only the records that come back in the error list.
Key Takeaways
BatchWriteRecord and ListRecords are additive to Feature Store’s existing APIs rather than replacements PutRecord, GetRecord, and DeleteRecord all continue to work as before. For teams running high-volume feature pipelines or needing to audit and clean up In-Memory tier data, the two new APIs remove workarounds that previously required either accepting the throughput ceiling of single-record calls or building custom tracking to avoid losing record identifiers entirely.
Key Takeaways
- BatchWriteRecord writes up to 25 records across one or more feature groups in a single call, with each record succeeding or failing independently (partial-success semantics).
- ListRecords enumerates record identifiers within a feature group via pagination, and is the first way to browse contents of the In-Memory (Redis-backed) storage tier, which previously had no offline-store fallback.
- Both APIs are available now through Boto3 and SageMaker Python SDK v3.8.0+, and require sagemaker:BatchWriteRecord / sagemaker:ListRecords IAM permissions on the feature group ARN.
- TTL on BatchWriteRecord can be set per record, per request, or inherited from the feature group, in that order of precedence.
FAQ
What is the maximum number of records BatchWriteRecord can write in one call?
Up to 25 entries per request, and that limit applies across all feature groups targeted in a single call, not per feature group.
Does ListRecords return the actual feature values, or just identifiers?
In this release, ListRecords returns record identifiers only. To get the underlying feature values for a given identifier, you still need to call GetRecord or BatchGetRecord.
Does ListRecords work with SageMaker Feature Store’s In-Memory tier?
Yes. ListRecords works with both the Standard tier (backed by Amazon DynamoDB) and the In-Memory tier (backed by Amazon ElastiCache for Redis), which is notable because the In-Memory tier previously had no way to enumerate or recover records at all.
If some records in a BatchWriteRecord call fail, does the whole request fail?
No. BatchWriteRecord uses partial-success semantics: successful writes are not rolled back if other records in the same request fail. AWS recommends retrying only the specific records returned in the Errors or UnprocessedEntries fields of the response.