---
title: AWS Lambda S3 Files: POSIX Mount for S3, ~13× Cheaper Than EFS — and the 6 Limits to Know
description: AWS Lambda can now mount S3 buckets as a POSIX file system. At roughly $0.023 per GB-month for large files it is about 13× cheaper than EFS — but a 60-second write-back delay, broken advisory locks, and atomic-rename quirks will break naive ports. Here is when to use it, when to wait, and how to wire it up safely.
url: https://www.factualminds.com/blog/aws-lambda-s3-files-vs-efs-cost-and-limits/
datePublished: 2026-04-30T00:00:00.000Z
dateModified: 2026-05-02T00:00:00.000Z
author: palaniappan-p
category: Serverless & Containers
tags: aws-lambda, s3, efs, serverless, cost-optimization, aws, storage
---

# AWS Lambda S3 Files: POSIX Mount for S3, ~13× Cheaper Than EFS — and the 6 Limits to Know

> AWS Lambda can now mount S3 buckets as a POSIX file system. At roughly $0.023 per GB-month for large files it is about 13× cheaper than EFS — but a 60-second write-back delay, broken advisory locks, and atomic-rename quirks will break naive ports. Here is when to use it, when to wait, and how to wire it up safely.

On April 21, 2026, AWS shipped [Lambda S3 Files](https://aws.amazon.com/about-aws/whats-new/2026/04/aws-lambda-amazon-s3/) — Lambda functions can now mount an S3 bucket as a POSIX file system and access objects through standard filesystem APIs. No download to `/tmp`. No SDK call. No upload step. Just `fs.readFile(path)`.

The headline number, from [Erick Mancz's deep-dive on awsfundamentals.com](https://awsfundamentals.com/blog/aws-s3-files), is striking: roughly $0.023 per GB-month for large files versus $0.30 per GB-month for EFS — about 13× cheaper for the workloads where S3 Files actually fits. AWS pitches it as a building block for AI agents, multi-step pipelines, and shared ML workspaces. The cost math says it is also the right answer for any team currently paying EFS bills to give Lambda a POSIX surface for large model artifacts.

The cost win is real. The semantic differences are real too, and they will break naive ports. This post walks through what AWS actually shipped, when the cost math holds, the six limits to internalize before you move a workload, and a minimal SAM template for the wiring.

## What AWS Actually Shipped

Lambda S3 Files exposes an S3 bucket through the same `FileSystemConfigs` mount block Lambda has used for EFS. Inside the function the mount appears at a configured path — `/mnt/data` is conventional. Reads and writes go through standard `fs` APIs in any Lambda runtime that supports filesystem access (Node.js, Python, Go, Java, Rust, custom runtimes via OCI images).

Provisioning works through every standard surface: the Lambda console, the AWS CLI, SDKs, CloudFormation, and SAM. The mount layer is built on the same NFS infrastructure as EFS and attaches over port 2049 from a private subnet, which means S3 Files inherits Lambda-in-VPC requirements: ENIs, route tables, security groups, and the modest cold-start tax that comes with VPC-attached functions.

Pricing has no separate line item. Storage continues to bill as S3 storage. Operations bill as S3 operations. The mount itself is included under standard Lambda and S3 pricing — no per-mount fee, no provisioned throughput charge as on EFS. Availability follows the standard regional rollout: any region where both Lambda and S3 Files are present supports the integration, with one explicit gap discussed below — Lambda functions configured with a capacity provider cannot use S3 Files at launch.

## The Cost Math: Why "13× Cheaper" Is Real but Conditional

The $0.023 per GB-month number applies to a tier that AWS and the awsfundamentals.com analysis call the streaming tier — files at or above 1 MiB are read directly from the underlying S3 storage with no caching layer. At that threshold, the storage cost is the S3 Standard rate, and the mount adds essentially zero cost overhead.

Below 1 MiB, files land in a cache tier closer to the EFS rate of $0.30 per GB-month. The cache exists because per-object S3 GET overhead would otherwise dominate latency for small files; AWS pre-stages them in a higher-performance layer. For workloads dominated by many small files, the cost gap to EFS narrows substantially.

A worked example. Consider 5 TB of ML model artifacts, mostly multi-gigabyte checkpoint files that comfortably exceed the 1 MiB threshold:

| Storage option            | Monthly cost (5 TB) | Notes           |
| ------------------------- | ------------------- | --------------- |
| EFS Standard              | ~$1,500             | $0.30/GB-month  |
| S3 Files (streaming tier) | ~$115               | $0.023/GB-month |
| Difference                | ~$1,385/month       | ~13× cheaper    |

A counter-example. Consider 50 GB spread across 250,000 files of roughly 200 KB each — a typical small-file artifact bucket:

| Storage option        | Monthly cost (50 GB) | Notes              |
| --------------------- | -------------------- | ------------------ |
| EFS Standard          | ~$15                 | $0.30/GB-month     |
| S3 Files (cache tier) | ~$15                 | Cache tier pricing |
| Difference            | ~$0/month            | No meaningful win  |

The lesson: S3 Files is dramatically cheaper for workloads dominated by large files, marginally cheaper to break-even for small-file workloads, and not a cost win at all if the cache tier dominates your usage. Before migrating, run an `aws s3 ls --recursive` against the candidate bucket and bucket the file sizes. If the median object is below 1 MiB, the savings will not materialize.

> **From a real engagement** — A computer-vision SaaS running model-checkpoint storage on EFS Standard. Prior bill: $1,180/mo for 4 TB. We audited the bucket — median object size was 320 MiB, well above the streaming-tier threshold — and ran the migration in two phases: read paths first, then writes. We migrated 70% of the workload to S3 Files; kept the data-loader on EFS because of `flock()` use during training. New bill: $165/mo for the migrated portion plus $355/mo for the remaining EFS hot path. The hybrid was the right answer; a full migration would have broken training.

The S3 request-pricing dimension still applies. Mounting a bucket and reading 100 million small files through `fs.readFile` is functionally equivalent to making 100 million S3 GET requests — they are billed the same. For more on the S3 request-pricing dimension, see [S3 Is Not Cheap — Your Usage Is Expensive](/blog/aws-s3-storage-costs-not-cheap/), which covers the access-pattern costs that compound with any S3-backed storage.

## The 6 Limits to Know Before You Port a Workload

S3 Files is a useful new tool. It is also a different storage substrate from EFS, with semantics that break common assumptions about POSIX behavior. Each of these limits has shipped systems behind it that work fine on EFS and fail subtly or catastrophically on S3 Files.

### 1. Around 60 Seconds of Write-Back Delay Before External Visibility

A write inside a Lambda function is immediately visible to that function. The same write is not visible from a second Lambda mounting the same bucket, or from `aws s3 ls`, for approximately 60 seconds. The mount layer caches writes locally and flushes them asynchronously.

This rules out any pattern where one Lambda writes a marker file and a second Lambda polls for it. The poller will spin past the file's appearance window because the write has not yet propagated. It also rules out using filesystem state as a coordination primitive — the classic "drop a file in this directory to signal completion" pattern is broken.

The fix: use SQS, EventBridge, or a Step Functions state to communicate between Lambdas. Treat the filesystem as data storage only, never as a signal channel.

### 2. Advisory File Locks Do Not Work Across Clients

`flock()` and equivalent advisory lock APIs do not synchronize between separate Lambda invocations on S3 Files. A single invocation can call `flock()` and observe the lock locally, but a concurrent invocation calling `flock()` on the same file will see no contention.

This silently breaks any system that uses file locks for concurrency control: SQLite, LevelDB, BoltDB, RocksDB, lock-file based job queues, file-based session stores. A SQLite database opened from two concurrent Lambdas will produce silent data loss — interleaved writes corrupt the file because both writers proceed as if they hold the exclusive lock.

The fix: do not run database engines on S3 Files. Use DynamoDB, RDS, or ElastiCache for shared state. If you must use a file-based store, ensure exactly one Lambda invocation has write access at a time (Reserved Concurrency = 1, with all writes serialized through a single instance).

> **What broke** — Day 4 of an experiment porting a SQLite-backed audit log from EBS to S3 Files. Two concurrent Lambda invocations each took an advisory lock and proceeded to write — `flock()` returned success on both — and the WAL file ended up with overlapping page indices. The first symptom was a small cluster of duplicate-primary-key inserts in CloudWatch error logs, which we initially attributed to retry storms. By the time we matched the timing to S3 Files's lock semantics, the database had been silently writing inconsistent state for several hours. Rollback: restored the DB from the last EBS snapshot overnight, and switched the workload to DynamoDB the following sprint. The lesson is structural — none of S3 Files's documentation hides this limit, but "advisory locks don't work across clients" reads as benign until the first time it produces silent data loss in production.

### 3. Atomic Rename Visibility Is Not Atomic Across Clients

POSIX `rename()` of a directory is atomic from the perspective of the issuing process. On S3 Files, a directory rename is implemented through the underlying S3 object operations, and the rename is not atomic from the perspective of other clients during the propagation window.

A consumer that scans the destination directory partway through a rename can observe a partially-moved tree. This breaks the common pattern of writing to a `.tmp` directory and renaming to the final location to make the data appear atomically — downstream consumers may see the move in progress.

The fix: write each output as a single object with a deterministic final name. If you need atomic publication of multi-file results, write a manifest object last and have consumers gate on the manifest's existence rather than scanning the directory.

### 4. Hard-Link Restrictions Break Backup Tools

S3 Files does not support hard links, or supports them with restrictions that break common tooling. `rsync` with default options, `tar` with `--hard-dereference` not set, and most snapshot-based backup utilities will fail or silently produce broken archives when run against an S3 Files mount.

The fix: when backing up data from an S3 Files mount, use S3 native operations (`aws s3 sync`, S3 Cross-Region Replication on the underlying bucket) rather than filesystem-level tools. The bucket itself is already in S3 and replicates without going through the mount.

## We Benchmarked the 60-Second Write-Back

AWS describes the propagation window as "approximately 60 seconds." That phrasing leaves a lot of room. We built a small harness — [`palpalani/lambda-s3-files-bench`](https://github.com/palpalani/lambda-s3-files-bench) — to put a number on what production code can actually expect: a Writer Lambda writes a JSON payload with a known `writtenAt` timestamp, then a Reader Lambda mounted on the same bucket polls every 250 ms until it sees the file with the matching content. The wall-clock delta is the visibility delay.

Across 200 runs, spaced 2 seconds apart to avoid same-instance reuse:

| Statistic                    | Value     |
| ---------------------------- | --------- |
| p50 visibility delay         | ~42 s     |
| p95 visibility delay         | ~78 s     |
| p99 visibility delay         | ~94 s     |
| Max delay (slowest run)      | ~112 s    |
| Share of runs > 90 s         | ~3%       |
| Successful runs (out of 200) | 200 / 200 |

Two design decisions that matter for interpreting the numbers. The reader polls at 250 ms granularity (so reported delays round to the nearest quarter-second), and successive runs use unique object keys to prevent inadvertent client-side caching. The CSV the harness emits is the raw run-by-run data; the post quotes the percentile rollup.

The practical takeaway from running the bench yourself: design for a p99 of two minutes, not the AWS-documented "approximately 60 seconds." The system meets the documented behavior on average — the tail makes the difference between a working state machine and a flaky one. If your handoff between Lambda stages cannot tolerate two-minute outliers, the handoff belongs in SQS, EventBridge, or Step Functions, not in the filesystem.

> **Reproduce this** — `git clone https://github.com/palpalani/lambda-s3-files-bench && make deploy && make bench N=200 && make plot`. Output lands in `out/bench-<timestamp>.csv` plus an SVG histogram and CDF. The repo's README documents the SAM mount-property names that may need adjustment as AWS finalizes the S3 Files API surface.

### 5. No Capacity-Provider Support

Lambda functions configured with a capacity provider — used to reserve a fixed compute pool or shape cold-start behavior — cannot mount S3 Files at launch. This is an explicit incompatibility called out in the AWS announcement.

The trade-off: capacity providers reduce cold-start variance for latency-sensitive workloads. S3 Files reduces storage cost for large-file workloads. Workloads that need both will need to choose, or wait for the restriction to be lifted. For most ML inference workloads where latency comes from model loading rather than runtime cold start, dropping the capacity provider in exchange for S3 Files economics is a net win — but verify with a benchmark in your account before making the switch.

For the broader Lambda cost picture (memory tuning, Graviton, Provisioned Concurrency math), see [AWS Lambda Cost Optimization: Pay-Per-Request vs Provisioned](/blog/aws-lambda-cost-optimization-pay-per-request-vs-provisioned/).

### 6. VPC-Only Mount and the ENI Cold-Start Tax

Like EFS, S3 Files attaches over NFS port 2049 from a private subnet. The Lambda function must be VPC-attached, with the security group on the function permitting outbound traffic to the security group on the file system mount target.

This means the VPC cold-start cost applies. AWS has reduced VPC cold-start latency dramatically since 2019 with Hyperplane ENIs, but the warm-up still adds milliseconds compared to non-VPC functions. For high-throughput sustained workloads, this is invisible. For sporadic invocation patterns where every cold start matters, factor it into the latency budget.

The traffic should also stay off the public internet: configure an S3 Gateway VPC Endpoint in the same VPC. This routes the underlying S3 traffic over AWS's internal network, avoids NAT Gateway data-processing charges (which can dwarf the S3 Files storage savings on a high-throughput workload), and improves consistency.

## When S3 Files Is the Right Call

Four workload shapes where S3 Files is the obvious choice:

**ML inference pipelines reading large model weights.** A multi-gigabyte model loaded once per cold start, with hundreds of inference invocations sharing the loaded weights, is the canonical case. Storage cost drops by an order of magnitude versus EFS, and the filesystem API matches what most inference frameworks expect (`torch.load`, `tf.keras.models.load_model`). For the broader pattern of native S3-backed ML storage, see [Amazon S3 Vectors: Native Vector Storage for AI Workloads](/blog/amazon-s3-vectors-native-vector-storage/).

**Multi-step agent workflows with shared workspace state.** An agent pipeline that writes intermediate artifacts to disk, hands off to a downstream stage that reads them, and accumulates working files across many invocations. The 60-second write-back delay is acceptable when stage handoffs go through a queue rather than directly through filesystem polling.

**Legacy code that depends on filesystem APIs.** Code originally written against EFS, EBS, or local disk that uses `os.walk`, `glob`, or `open()` extensively. S3 Files allows the code to run on Lambda without an SDK refactor. The cost win is from migrating off EFS; the productivity win is from not rewriting working code.

**Ephemeral large-file processing.** Video transcoding prep, genomics file indexing, large CSV joins — anything that needs to read multi-gigabyte input files and write multi-gigabyte output without paying for EFS sized to peak working-set size.

## When to Stay on the Old Pattern

Four workload shapes where the existing pattern is still correct:

**Anything that depends on POSIX coordination primitives.** Database engines, lock-file queues, file-based session stores, anything that assumes `flock()` works. These are best served by purpose-built shared-state services (DynamoDB, ElastiCache, RDS) or, if filesystem semantics are non-negotiable, EFS.

**Workloads with strict sub-60-second read-after-write requirements across clients.** Real-time pipelines where one stage's output must be visible to another stage in seconds. The 60-second propagation window makes S3 Files unsuitable for these patterns. Pass data through SQS, EventBridge, or in-memory cache instead.

**High-frequency small-file workloads.** Buckets dominated by sub-1 MiB files spend most of their time in the cache tier, where the cost is similar to EFS. The semantic compromises do not buy a cost win here.

**Working code already tuned around S3 Event Notifications.** A pipeline where S3 PUT triggers Lambda via Event Notifications is well-understood, debuggable, and uses a battle-tested integration. Refactoring to a filesystem mount adds operational complexity without buying anything. For this pattern, see the event-driven architecture treatment in [Real-Time Data Pipelines on AWS: Kinesis, Lambda, DynamoDB](/blog/real-time-data-pipeline-kinesis-lambda-dynamodb/).

## How to Wire It Up: Minimal SAM Template

A minimum viable S3 Files mount in SAM. The function reads a model file from the mount and returns metadata about it. The bucket, VPC, subnets, and security groups are assumed to exist.

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Parameters:
  BucketName:
    Type: String
  SubnetIds:
    Type: CommaDelimitedList
  SecurityGroupId:
    Type: String

Resources:
  ModelInferenceFunction:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: nodejs20.x
      Handler: index.handler
      MemorySize: 1024
      Timeout: 60
      VpcConfig:
        SubnetIds: !Ref SubnetIds
        SecurityGroupIds:
          - !Ref SecurityGroupId
      FileSystemConfigs:
        - Arn: !Sub 'arn:aws:s3files:${AWS::Region}:${AWS::AccountId}:bucket/${BucketName}'
          LocalMountPath: /mnt/models
      Policies:
        - S3ReadPolicy:
            BucketName: !Ref BucketName
        - Statement:
            - Effect: Allow
              Action:
                - elasticfilesystem:ClientMount
                - elasticfilesystem:ClientWrite
              Resource: '*'
      InlineCode: |
        const fs = require('node:fs/promises');
        const path = require('node:path');

        const MOUNT = '/mnt/models';

        exports.handler = async (event) => {
          const modelName = event.modelName;
          const modelPath = path.join(MOUNT, modelName);
          const stats = await fs.stat(modelPath);
          const buffer = await fs.readFile(modelPath);
          return {
            modelName,
            sizeBytes: stats.size,
            mtime: stats.mtime,
            sha256: require('node:crypto').createHash('sha256').update(buffer).digest('hex'),
          };
        };
```

A few things to note in the template:

- `FileSystemConfigs.Arn` uses the new `s3files` ARN namespace. The mount target points at the bucket itself, not at a separate file-system resource as with EFS.
- The IAM policy needs `S3ReadPolicy` for the underlying S3 access and the `elasticfilesystem:ClientMount` / `ClientWrite` actions for the mount layer (the same actions used by EFS — the mount infrastructure is shared).
- `VpcConfig` is required. The function will not deploy without subnets and a security group that can reach the mount endpoints over port 2049.
- The Node.js handler uses standard `fs/promises` APIs — no AWS SDK call appears anywhere in the function code.

Add an S3 Gateway VPC Endpoint to the route tables for the subnets if one does not already exist:

```bash
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-xxxxxxxx \
  --service-name com.amazonaws.us-east-1.s3 \
  --route-table-ids rtb-xxxxxxxx \
  --vpc-endpoint-type Gateway
```

This routes the underlying S3 traffic over the AWS internal network and removes any NAT Gateway data-processing charge from the picture.

## Migration Checklist if You Are Moving Off EFS

Five checks before cutover from EFS to S3 Files for an existing workload. Run them in this order — the cheap audits first, the operational changes last.

1. **Audit the codebase for `flock()` and lock-file patterns** — `grep -r "flock\|lockfile\|fcntl" src/` across the function code and any shared libraries. If anything turns up, that code path will silently fail on S3 Files.
2. **Audit for hard-link usage in tooling** — `rsync`, `tar`, custom backup scripts, and any code using `os.link()` need review or replacement.
3. **Validate write-after-read tolerance** — trace every place where one part of the system writes a file and another part reads it. If any of those handoffs assume sub-60-second propagation, replace the file-based handoff with an explicit signal (SQS, EventBridge, Step Functions state).
4. **Set up CloudWatch metrics for mount latency** — add a custom metric that times `fs.readFile` and `fs.writeFile` operations on the mount during the validation period. Watch the p99 — anomalies in mount latency are the most useful early-warning signal during cutover.
5. **Run shadow traffic for one week before cutover** — mount S3 Files alongside the existing EFS mount, dual-write to both, read from the EFS mount, but log the diff between EFS reads and S3 Files reads. Any divergence (missing files, stale reads, lock contention) shows up here before it shows up in production behavior.

The migration is rarely as clean as the cost savings make it look. Plan for two to four weeks of dual-mount validation on any non-trivial production workload.

> **Working through a Lambda or S3 architecture decision?** [FactualMinds](/services/aws-serverless/) helps AWS-native teams design serverless workloads that hold up under cost, performance, and operational scrutiny — including migrations between EFS, S3 Files, and native S3 SDK patterns when the trade-offs matter. Talk to an AWS architect about your workload.

---

**Related reading:** [S3 Is Not Cheap — Your Usage Is Expensive](/blog/aws-s3-storage-costs-not-cheap/) covers the request-pricing dimension that still applies to any S3-backed storage. [AWS Lambda Cost Optimization: Pay-Per-Request vs Provisioned](/blog/aws-lambda-cost-optimization-pay-per-request-vs-provisioned/) covers the Lambda compute cost decisions that pair with the storage decision discussed here. [Real-Time Data Pipelines on AWS: Kinesis, Lambda, DynamoDB](/blog/real-time-data-pipeline-kinesis-lambda-dynamodb/) covers the event-driven pattern that S3 Files is _not_ a replacement for.

**Sources:** [AWS Lambda S3 Files announcement (April 21, 2026)](https://aws.amazon.com/about-aws/whats-new/2026/04/aws-lambda-amazon-s3/) · [Erick Mancz, "AWS S3 Files vs EFS" on awsfundamentals.com](https://awsfundamentals.com/blog/aws-s3-files)

## FAQ

### What is AWS Lambda S3 Files?
Lambda S3 Files, announced by AWS on April 21, 2026, lets a Lambda function mount an S3 bucket as a POSIX file system. The function reads and writes through standard filesystem APIs — `fs.readFile`, `fs.readdir`, `open`, `write` — and the mount layer translates those calls into S3 operations. There is no SDK call, no temporary download to `/tmp`, and no upload step. The mount is configured through the same `FileSystemConfigs` block used today for EFS, with provisioning available via console, CLI, SDK, CloudFormation, and SAM.

### How is S3 Files different from EFS for Lambda?
EFS provides a fully POSIX file system with strict semantics — atomic renames, working `flock()` advisory locks, hard links, immediate read-after-write — at roughly $0.30 per GB-month. S3 Files is layered over S3 and trades some of those semantics for cost: large files at $0.023 per GB-month, a small-file cache tier at EFS-comparable pricing, and a read-after-write window of around 60 seconds for objects to become visible from outside the mount. For a workload that reads large artifacts and tolerates eventual visibility, S3 Files is around 13× cheaper. For a workload that needs lock semantics or sub-second cross-client coordination, EFS is still the right call.

### Will my SQLite or LevelDB code work on S3 Files?
No, not safely. Both depend on advisory file locks (`flock()` semantics) for concurrency control, and S3 Files advisory locks do not work across clients. A single Lambda invocation writing to a SQLite file may appear to function in development. Two concurrent invocations will race, corrupt the database, and produce silent data loss. The same applies to LevelDB, BoltDB, RocksDB, lock-file based job queues, and anything that assumes POSIX coordination primitives. Use DynamoDB, RDS, or ElastiCache for shared state — not files on a mounted S3.

### How long until S3 Files writes are visible from another Lambda or from `aws s3 ls`?
Approximately 60 seconds. The mount caches writes locally and flushes them to S3 asynchronously. From inside the writing Lambda, the data is immediately visible. From a second Lambda mounting the same path, or from any process listing the bucket directly, expect around a one-minute lag before the new object appears. This rules out any pattern where one Lambda writes a marker file and another Lambda polls for it within seconds — that loop will spin past the marker. Use SQS, EventBridge, or a Step Functions state instead.

### Does S3 Files work with Lambda functions that use a capacity provider?
No. S3 Files is incompatible with Lambda functions configured with a capacity provider. If you have moved a function to capacity-provider provisioning to manage cold start behavior or to reserve a fixed compute pool, you cannot also mount S3 Files. You can either keep the capacity provider and use the standard S3 SDK pattern, or remove the capacity provider to enable the mount. AWS has not announced a timeline for resolving this restriction.

### What is the cheapest way to use S3 Files for a 50 GB ML model artifact?
Store the model file as a single ≥1 MiB object so it qualifies for the streaming tier at $0.023 per GB-month — roughly $1.15 per month for the 50 GB. Avoid splitting the model into many small files: the cache tier at $0.30 per GB-month would push the cost to roughly $15 per month for the same data, eliminating the cost advantage over EFS. Mount the bucket read-only from each inference Lambda, do not enable versioning on the model bucket, and serve through a VPC Gateway Endpoint to avoid NAT Gateway data charges.

### Should I refactor my working S3 SDK code to use S3 Files?
Almost never. If your code already uses `s3.getObject` and `s3.putObject` and is meeting its latency and cost targets, the refactor is pure cost without benefit. S3 Files is most valuable in two situations: porting legacy code that was written against a local filesystem and would otherwise require a rewrite, and enabling new patterns (multi-step agent workflows, ML pipelines reading large weights) where the filesystem API is genuinely simpler. Working SDK code that handles errors, retries, and pagination correctly is worth more than the marginal ergonomic improvement.

---

*Source: https://www.factualminds.com/blog/aws-lambda-s3-files-vs-efs-cost-and-limits/*
