AWS Storage

Amazon EFS Hands-On: Shared NFS File Storage Across Instances, Containers & Lambda

Quick take: Amazon EFS (Elastic File System) is a fully-managed NFSv4.1 file system that many machines mount at once — the one AWS storage service where a file written by an EC2 instance in us-east-1a is readable, a millisecond later, by another instance in us-east-1b, by a Fargate task, and by a Lambda function, all at the same time. That single fact — shared, concurrent, multi-AZ, POSIX — is what separates it from EBS, which attaches to exactly one instance in one AZ. Almost everything that matters about operating EFS comes down to five choices: how clients reach it (mount targets — one elastic network interface per AZ, each with a security group that must allow NFS on TCP 2049); how fast it goes (throughput mode — Elastic, Bursting or Provisioned — and the burst-credit trap that throttles small file systems); what it costs (storage classes — Standard, One Zone, IA, Archive — plus lifecycle management that tiers cold files automatically); how you isolate apps on one file system (access points that pin a POSIX user and root directory); and how you secure it (KMS at rest, TLS in transit via amazon-efs-utils, and EFS IAM authorization). Get those right and EFS is invisible shared storage that scales to petabytes with no capacity planning. Get them wrong and your mount hangs for sixty seconds and times out, your writes fail with permission denied, your throughput falls off a credit cliff in production, or your bill quietly triples because nothing ever moved to Infrequent Access. This article takes every one of those apart, then does all of it hands-on with aws CLI and Terraform.

You reach for EFS the first time two machines need to see the same files. A pair of web servers behind a load balancer that must both serve the same user uploads. A content-management cluster where every node reads the same wp-content directory. A machine-learning fleet where dozens of training instances read one shared dataset. A container platform where pods come and go but their data must persist and be shared. In every one of these, the block-storage answer — attach an EBS volume — fails at the first requirement, because an EBS volume belongs to one instance in one Availability Zone and cannot be in two places at once. EFS is the answer built for exactly this: a network file system that presents a normal POSIX directory tree (/mnt/efs/uploads/...), that any number of clients across every AZ in the Region can mount simultaneously, and that grows and shrinks automatically as you add and delete files — you never provision capacity, you never run out, and you never see a disk to resize.

This guide is the complete, decision-by-decision treatment of EFS for someone who has to actually run it in production. We define what a managed NFS file system really is and how it differs from EBS block storage, S3 object storage and the FSx family; we take mount targets apart down to the ENI and the one security-group rule that causes 80% of “my mount hangs” tickets; we go mode by mode through performance modes (General Purpose vs the legacy Max I/O) and throughput modes (Elastic, Bursting, Provisioned) with the exact baseline and burst-credit numbers; we enumerate every storage class and build a lifecycle policy that tiers cold data to IA and Archive for up to 90% less; we use access points to jail three apps into one file system safely; we turn on encryption at rest and in transit and lock mounts down with EFS IAM; and we mount the same tree from EC2, from ECS and EKS (the EFS CSI driver), and from Lambda. Then we do the whole thing hands-on and finish with a troubleshooting playbook you will come back to mid-incident.

By the end you can create an EFS file system with mount targets in two AZs behind a correct NFS security group, mount it on two instances in different AZs and watch a file written on one appear on the other, carve out a per-app access point with an enforced POSIX identity, turn on lifecycle to Infrequent Access, and mount the same file system from a container and a Lambda — every step as both an aws CLI command and Terraform. This maps to the storage domains of CLF-C02 (Cloud Practitioner), SAA-C03 (Solutions Architect Associate) and SOA-C02 (SysOps Administrator).

What problem this solves

The problem EFS solves is shared, persistent, POSIX file storage that scales itself and is reachable by many compute instances at once across Availability Zones. Three constraints make it a distinct problem from the storage you already know. First, sharing: more than one machine must read and write the same files concurrently, with normal file semantics (open, seek, write, lock, ls, chmod). Second, elasticity across a fleet that changes: instances scale in and out, containers are ephemeral, Lambdas are stateless — the data has to outlive and be shared by all of them without anyone attaching, detaching, or resizing a disk. Third, multi-AZ durability and availability: the storage must survive an entire Availability Zone going down and still be mountable from the AZs that remain.

Block storage cannot meet the first constraint at all. An EBS volume attaches to a single instance (Multi-Attach exists but requires io1/io2 and a cluster-aware filesystem and is a niche HA pattern, not general file sharing). Put your shared uploads on EBS and your second web server simply cannot see them. Object storage (S3) is shared and infinitely scalable but is not a filesystem: you can’t mount it, can’t open()/seek()/append, can’t run a legacy app or a CMS that expects a POSIX path — you rewrite the app to speak the S3 API. EFS is the piece in the middle: a real mounted filesystem that behaves like a local disk to every app, but is shared, elastic and multi-AZ.

What breaks without understanding it is rarely the creation — the console makes a file system in three clicks. It’s everything about reaching it and paying for it. You create the file system, run mount, and it hangs for sixty seconds then fails because the mount target’s security group doesn’t allow port 2049 from your instance — the single most common EFS failure, and one that produces no useful error, just a timeout. You mount successfully but every write is permission denied because the NFS export maps your user to nobody and the directory is owned by root. Your app flies in a load test and then throttles to a crawl in production because you left it on Bursting throughput and the burst credit bucket — which fills only in proportion to how much data you store — drained to zero. And three months later Finance asks why a file system holding mostly untouched log archives costs $0.30/GB-month when it could be $0.016 — because nobody enabled lifecycle management. Every one of these is specific, avoidable, and in this article.

Who hits this: anyone running stateful workloads on more than one instance. It bites hardest on teams putting a CMS (WordPress, Drupal, Magento) behind an Auto Scaling group; on container platforms needing ReadWriteMany persistent volumes; on ML/analytics fleets sharing datasets; on lift-and-shift migrations of on-prem NFS/NAS; and on anyone whose first EFS mount silently times out with no clue why. Here is the whole field in one frame — the five questions every EFS file system silently forces you to answer:

The question The default (if you don’t decide) What it costs to get wrong Where in this article
How do clients reach it? Mount targets you must create per AZ; SG defaults vary Mount hangs/times out (no mount target in the AZ, or SG blocks 2049) Mount targets, security groups and the NFS path
How fast does it go? Elastic (new console default); Bursting on older ones Prod throttles when Bursting credits drain, or you overpay for Provisioned Performance modes and throughput modes
What does it cost? Standard ($0.30/GB-mo), no lifecycle 3–20× overpay on cold data with no lifecycle to IA/Archive Storage classes and lifecycle management
How do apps stay isolated? Everyone mounts root as root One app stomps another’s files; no POSIX enforcement Access points and POSIX isolation
How is it secured? At-rest encryption on by default (new); in-transit off unless you ask Plaintext on the wire; any VPC client can mount Encryption and EFS IAM authorization

Learning objectives

By the end of this article you can:

Prerequisites & where this fits

You need an AWS account, the AWS CLI v2 configured with a non-root IAM identity, and a VPC with at least two subnets in two Availability Zones plus one or two EC2 instances you can reach — if launching and connecting to an instance is new, start with Launch Your First EC2 Instance and Connect: SSH, Instance Connect & Session Manager. You should be comfortable at a Linux shell (mount, df, ls -l, editing /etc/fstab) and recognize a security group rule when you see one. Terraform appears next to every CLI snippet; you don’t need fluency, only to read a resource block.

This sits in the Storage track as the shared-file counterpart to block storage. Where Amazon EBS Hands-On: Volume Types, Snapshots, Resizing & Encryption gives one instance a fast private disk, EFS gives a whole fleet one shared disk — the two are complementary, not competing (a database goes on EBS; the shared uploads directory goes on EFS). EFS is also the natural persistence layer when you move to containers: the AWS ECS vs EKS vs Fargate: Choose Your Container Path decision determines how you mount it (task volume vs the EFS CSI driver), and in a layered web stack like The Classic AWS Three-Tier Web Application Architecture: VPC, ALB, Auto Scaling and RDS Done Right, EFS is where the web tier’s shared state lives so any instance behind the ALB can serve any request.

Here’s the assumed knowledge, why each piece matters specifically for EFS, and where to shore it up:

You should know… Why it matters here Brush up
What a VPC, subnet and AZ are A mount target lives in one subnet/AZ; clients mount the one in their AZ Launch Your First EC2 Instance
How a security group filters traffic The mount target SG must allow TCP 2049 from clients Mount targets, below
Basic Linux mount / /etc/fstab You mount NFS by hand and persist it across reboots Any Linux primer
POSIX permissions (uid/gid, chmod) Access points and NFS export mapping are all POSIX Access points, below
The difference between block, file, object storage Explains why EFS, not EBS or S3, for shared files Core concepts, below
That EBS is single-AZ, single-instance The exact gap EFS fills Amazon EBS Hands-On

Core concepts

Seven mental models make every later decision obvious.

EFS is a managed NFS server you never see. You get an NFSv4.1 (and 4.0) endpoint per Availability Zone and a DNS name; behind it AWS runs a horizontally-scaled, fault-tolerant fleet that stores your files redundantly across multiple AZs. You never patch it, never scale it, never see a “server.” Your instance runs a standard NFS client (or the AWS amazon-efs-utils helper) and mounts it at a path. Everything a normal filesystem does — directories, permissions, symlinks, byte-range locks, open/read/write/append — works, over the network, shared.

It is regional and multi-AZ; the file system is not pinned to one AZ (Standard is not). Unlike an EBS volume (locked to one AZ) or an S3 bucket (regional object store), a Standard EFS file system stores every byte redundantly across three or more Availability Zones in the Region. That is why it survives an AZ outage and why clients in any AZ can mount it. The exception is the One Zone storage class, which — as the name says — keeps data in a single AZ for lower cost and lower durability.

You reach the file system through a mount target — one per AZ. A mount target is an elastic network interface (ENI) that AWS places into a subnet you choose, giving the file system a private IP and DNS name reachable from that AZ. You create one mount target per Availability Zone you want to mount from, each attached to a security group. A client mounts the file system by its DNS name; AWS resolves that to the mount target IP in the client’s own AZ (cross-AZ mounts work but add latency and cross-AZ data cost). No mount target in an instance’s AZ, or a security group that blocks the NFS port, and the mount hangs.

NFS is TCP port 2049 — that one rule governs connectivity. The entire client-to-EFS conversation is NFS over TCP 2049. The mount target’s security group must allow inbound 2049 from wherever your clients are (their security group, or their subnet CIDR). This is the whole networking story, and getting it wrong is the number-one EFS failure. There are no other ports to open for a modern amazon-efs-utils TLS mount.

Block vs file vs object — why EFS, not EBS or S3. A block device (EBS) is a raw disk one instance formats and mounts — lowest latency, but single-attach. Object storage (S3) stores whole objects by key over HTTP — infinitely scalable and cheap, but not mountable and not POSIX. File storage (EFS) is a shared network filesystem many instances mount over NFS — POSIX semantics and concurrent sharing, at network-filesystem latency (single-digit-ms for General Purpose mode). Choosing EFS means choosing “many clients, real files, shared, elastic — and I accept NFS latency over local-disk latency.”

Property EFS (file) EBS (block) S3 (object) Instance store (local block)
Access model NFS mount, many clients at once Mount as a disk (one instance) HTTP GET/PUT by key Mount as a disk (that host only)
Concurrent multi-instance Yes — thousands, all AZs No (single-attach) Yes (API, not a mount) No
Scope / resilience Region, multi-AZ (Standard) One AZ Region, 11 9s On the physical host
Capacity Elastic — grows/shrinks automatically Fixed size you resize Unlimited Fixed at launch
POSIX filesystem semantics Yes Yes (your FS) No Yes
Latency Single-digit ms (network) Sub-ms to low-ms (local net) Tens of ms (HTTP) Lowest (local NVMe)
Survives instance stop? Yes Yes N/A No
Price ballpark (us-east-1) $0.30/GB-mo (Standard) $0.08/GB-mo (gp3) $0.023/GB-mo (Standard) Included in instance
Typical use Shared uploads, CMS, home dirs, ML datasets, container RWX Boot disk, database, single-node app state Files, backups, static web, data lake Scratch, cache, temp

Throughput and IOPS are managed, not provisioned (with Elastic). With the modern Elastic throughput mode you do not provision anything — EFS delivers the read and write throughput your workload demands and bills per GB transferred. The older Bursting mode ties baseline throughput to how much you store (50 KB/s per GB) and lets you burst using a credit bucket; the small-file-system-that-throttles trap lives here. Provisioned mode lets you buy a fixed throughput independent of size.

Access points are the multi-tenancy primitive. An access point is a named entry point into the file system that enforces a POSIX user (uid/gid) and a root directory. Mount through an access point and you are transparently jailed to, say, /app-a, acting as uid 1000 no matter who you are on the client — so three apps can share one file system without seeing or corrupting each other’s data. Access points are how you do per-app isolation and how ECS/EKS/Lambda integrations bind to a subtree.

The vocabulary in one table

Pin down every moving part before the deep sections; the glossary repeats these for lookup:

Term One-line definition Why it matters
File system The EFS resource (fs-…), regional, elastic The thing you create; holds the directory tree
Mount target An ENI in one subnet/AZ with an IP + SG How clients in that AZ reach the file system
Security group (on the MT) Firewall on the mount target ENI Must allow inbound TCP 2049 from clients
NFSv4.1 The protocol clients speak to EFS Port 2049; locking, POSIX, TLS-wrappable
Access point Enforced POSIX user + root dir (fsap-…) Per-app isolation and container/Lambda binding
Performance mode General Purpose or Max I/O Latency vs aggregate-IOPS trade-off (set at create)
Throughput mode Elastic / Bursting / Provisioned How fast, and how you pay for speed
Burst credits Bucket that funds bursts above baseline Drains on small/busy Bursting file systems → throttle
Storage class Standard / One Zone / IA / Archive Durability + price tier of stored bytes
Lifecycle management Auto-transition by access age Moves cold files to IA/Archive to cut cost
amazon-efs-utils AWS mount helper (mount -t efs) Adds TLS (stunnel) + IAM + DNS convenience
EFS IAM authorization IAM policy gating the mount ClientMount/ClientWrite/ClientRootAccess
_netdev / tls fstab options for EFS _netdev waits for network; tls encrypts in transit

To orient before the deep dive, here are the moving parts you’ll configure, at a glance — the one-liner the next sections make rigorous:

Component You create it… The one thing to remember
File system once, per Region Elastic; encrypted at rest by default (new)
Mount target one per AZ Its SG must allow 2049; place in the client subnet
Access point per app/tenant Pins uid/gid + root dir — enforced, not advisory
Throughput mode at create (changeable) Elastic is the modern default; Bursting throttles small FS
Lifecycle policy after create Transitions to IA/Archive by access age — big cost lever

Mount targets, security groups and the NFS path

This is the section people get wrong first, because the file system creates cleanly and the failure only appears when a client tries to mount. A mount target is the only way a client reaches an EFS file system, and it is a real network object with an IP, an AZ, and a firewall.

What a mount target actually is

When you create a mount target you specify the file system, a subnet (which fixes the AZ), and one or more security groups. AWS provisions an elastic network interface in that subnet, assigns it a private IP from the subnet’s range, and that ENI becomes the NFS endpoint for that Availability Zone. The file system’s DNS name (fs-0abc123.efs.us-east-1.amazonaws.com) resolves, from within the VPC, to the mount target IP in the resolver’s AZ.

Mount target property Detail Consequence
Count One per Availability Zone (max) You need one MT in each AZ you mount from
What it is An ENI in a subnet, with a private IP Consumes one IP from the subnet CIDR
Security group(s) Up to 5 SGs on the ENI Must allow inbound TCP 2049 from clients
DNS resolution FS DNS → the MT IP in the client’s AZ Requires VPC DNS resolution + hostnames enabled
Lifecycle creatingavailable Wait for available before mounting
One Zone file system Exactly one mount target (its single AZ) Cross-AZ mount incurs latency + data charge
Deletion Delete MTs before deleting the file system Orphan MTs block file-system delete

⚠️ The “one mount target per AZ” rule is the whole availability story. If your Auto Scaling group can launch instances in us-east-1a, 1b and 1c, you need a mount target in all three. An instance that lands in an AZ with no mount target will hang on mount forever — and because ASG placement is non-deterministic, this shows up as “it works most of the time,” the worst kind of bug.

The one security-group rule that matters

NFS is TCP port 2049. For a client to mount, the mount target’s security group must allow inbound 2049 from the client. The cleanest, least-privilege way is to allow it from the client’s security group (a security-group reference), not from a CIDR — that way any instance carrying the client SG can mount, and nothing else can.

Rule direction On which SG Protocol / port Source / dest Why
Inbound Mount target SG TCP 2049 Client SG (sg-ref) Lets clients open the NFS connection
Outbound Client SG TCP 2049 Mount target SG / subnet Usually covered by default allow-all egress
(No other ports) Modern TLS mount uses only 2049 (stunnel wraps it)
# Allow NFS from the client SG to the mount target SG (least privilege)
aws ec2 authorize-security-group-ingress \
  --group-id sg-mounttarget \
  --protocol tcp --port 2049 \
  --source-group sg-clients
resource "aws_security_group" "efs_mt" {
  name   = "efs-mt-sg"
  vpc_id = var.vpc_id
  ingress {
    description     = "NFS from clients"
    from_port       = 2049
    to_port         = 2049
    protocol        = "tcp"
    security_groups = [aws_security_group.clients.id]   # SG reference, not CIDR
  }
  egress { from_port = 0  to_port = 0  protocol = "-1"  cidr_blocks = ["0.0.0.0/0"] }
}

The DNS name and how a mount resolves

You mount by the file system’s DNS name, and getting resolution right requires two VPC settings and (for a fresh instance) a moment’s patience:

Requirement Setting / command Symptom if wrong
VPC DNS resolution enableDnsSupport = true on the VPC DNS name won’t resolve; mount fails
VPC DNS hostnames enableDnsHostnames = true on the VPC Regional/AZ DNS names don’t resolve
Mount target available describe-mount-targetsavailable Mount hangs if MT still creating
Resolve from the right AZ Let DNS pick the local MT Cross-AZ mount = higher latency + data cost
IP fallback (no DNS) Mount the mount target IP directly Works, but you lose AZ-local auto-selection

The two DNS naming forms you’ll see:

Form Example Resolves to
File system DNS fs-0abc123.efs.us-east-1.amazonaws.com The mount target IP in the caller’s AZ
Mount target IP 10.0.1.20 That specific AZ’s mount target directly

Performance modes and throughput modes

EFS performance is governed by two independent settings: a performance mode (a latency-vs-parallelism choice, fixed at creation) and a throughput mode (how fast and how you pay, changeable). Conflating them is a common source of confusion.

Performance modes: General Purpose vs Max I/O

Aspect General Purpose (default) Max I/O (legacy)
Latency per operation Lowest (single-digit ms) Higher (tens of ms)
Aggregate IOPS ceiling High but capped per file system Higher aggregate, more parallel clients
Set when At creation — cannot change later At creation — cannot change later
AWS recommendation Use it for virtually everything Not recommended for new file systems
Watch PercentIOLimit climbing toward 100% Rarely needed with Elastic throughput
Use it for Web, CMS, home dirs, most container/ML Only massively-parallel legacy cases

General Purpose is the right answer for essentially every workload. It gives the lowest latency, and with Elastic throughput its historical IOPS ceilings have been raised substantially. Max I/O trades latency for a higher aggregate IOPS ceiling and was designed for tens of thousands of clients hammering one file system in parallel; AWS now steers you away from it for new file systems (Elastic throughput on General Purpose covers those cases better). The one signal that General Purpose is nearing its limit is the CloudWatch PercentIOLimit metric — if it sits near 100%, you’re I/O-bound; the modern fix is Elastic throughput, not Max I/O.

⚠️ Performance mode is permanent. You choose General Purpose or Max I/O when you create the file system and you can never change it. To switch, you create a new file system and copy the data (DataSync or rsync). Choose General Purpose unless you have a proven, measured reason not to — and in 2026 you almost never do.

Throughput modes: Elastic, Bursting, Provisioned

Mode How throughput is set How you pay Pick it when
Elastic (modern default) Automatic — scales to demand Per GB read/write transferred Spiky or unknown workloads; the default choice
Bursting Tied to size: 50 KB/s per GB baseline + burst Included in storage price Steady workloads whose throughput tracks their data size
Provisioned Fixed MB/s you set, independent of size Storage + provisioned throughput Small data but high, steady throughput needs

Elastic is the modern default and the safe choice. You provision nothing; EFS supplies read and write throughput up to high per-file-system limits (region-dependent — on the order of several GB/s read and ~1 GB/s write) and bills only for the data you actually move. For a workload whose throughput you can’t predict — which is most of them — Elastic removes the entire class of throttling bugs.

The Bursting burst-credit model (the throttling trap)

Bursting mode is where small file systems mysteriously throttle, so understand its arithmetic:

Bursting mechanic Value Consequence
Baseline throughput 50 KB/s per GB of Standard storage A 10 GB FS gets only ~0.5 MB/s baseline
Burst throughput 100 MB/s per TB stored (min 100 MB/s) Small FS can burst 100 MB/s but only briefly
Credit earning Earns credits whenever below baseline Idle time refills the bucket
Credit spending Spends credits whenever above baseline Sustained load drains it
New file system Starts with a credit allowance Flies at first, then falls to baseline
The trap Tiny FS + sustained load = throttle to baseline Demo is fast, production crawls
The signal BurstCreditBalance trending to 0 The fingerprint of this failure

The classic Bursting failure: you store 20 GB and run a busy CMS on it. Baseline is 20 × 50 KB/s = 1 MB/s. New file systems start with a generous credit balance so the demo is snappy; a week into production the credits drain and every file read slows to a 1 MB/s crawl, and no error is logged. The fix is one API call — switch to Elastic (or, if you truly want a fixed floor, Provisioned). This is why new file systems now default to Elastic.

# Move a throttling Bursting file system to Elastic — no downtime, no remount
aws efs update-file-system --file-system-id fs-0abc123 --throughput-mode elastic
# Or set a fixed floor with Provisioned:
aws efs update-file-system --file-system-id fs-0abc123 \
  --throughput-mode provisioned --provisioned-throughput-in-mibps 100
resource "aws_efs_file_system" "this" {
  creation_token   = "app-shared"
  performance_mode = "generalPurpose"   # permanent choice
  throughput_mode  = "elastic"          # modern default; avoids burst-credit throttling
  encrypted        = true
}

Storage classes and lifecycle management

EFS stores each file in a storage class, and a lifecycle policy moves files between classes automatically by how recently they were accessed. This is the single biggest cost lever on EFS, and the one most often left off.

The storage classes

Storage class Durability / AZs Access latency Price (us-east-1, approx) Use it for
Standard Multi-AZ (≥3) Low (ms) $0.30/GB-mo Hot, frequently-accessed files
Standard-IA (Infrequent Access) Multi-AZ (≥3) Slightly higher first-byte $0.016/GB-mo Files not accessed for days/weeks
Archive Multi-AZ (≥3) Higher first-byte $0.008/GB-mo Rarely accessed, kept online
One Zone Single AZ Low (ms) $0.16/GB-mo Dev/test, reproducible data, cost-first
One Zone-IA Single AZ Slightly higher first-byte $0.0133/GB-mo Cold data where single-AZ is acceptable

Two axes here: durability (Standard/IA/Archive are multi-AZ; One Zone variants live in a single AZ, ~47% cheaper but lost if that AZ is destroyed) and access frequency (Standard is hot; IA and Archive are progressively colder and cheaper per GB but add a per-GB retrieval charge and slightly higher latency on access).

Standard vs One Zone Standard One Zone
AZs storing data 3 or more 1
Survives an AZ loss Yes No (data lost if that AZ is destroyed)
Storage price $0.30/GB-mo $0.16/GB-mo (~47% less)
Mount targets One per AZ (multi-AZ) One (the single AZ)
Use it for Production shared data Dev/test, easily-reproducible data

Lifecycle management — transition by access age

A lifecycle policy has up to three independent rules: when to move a file to IA, when to move it to Archive, and whether to move it back to Standard on access. “Access age” means time since the file was last read or written.

Lifecycle setting Allowed values What it does
TransitionToIA 1, 7, 14, 30, 60, 90, 180, 270, 365 days (or AFTER_1_DAY…) Move a file to Standard-IA after N days of no access
TransitionToArchive ≥ 90 days (and ≥ the IA setting) Move to Archive after N days of no access
TransitionToPrimaryStorageClass AFTER_1_ACCESS (or none) On first read, move it back to Standard
Scope Whole file system Applies to all files by their own access age
Effect Automatic, transparent Files stay in the same path; only the class changes
# Transition to IA after 30 days idle, Archive after 90, and bring back to Standard on access
aws efs put-lifecycle-configuration --file-system-id fs-0abc123 \
  --lifecycle-policies \
    '{"TransitionToIA":"AFTER_30_DAYS"}' \
    '{"TransitionToArchive":"AFTER_90_DAYS"}' \
    '{"TransitionToPrimaryStorageClass":"AFTER_1_ACCESS"}'
resource "aws_efs_file_system" "this" {
  creation_token  = "app-shared"
  throughput_mode = "elastic"
  encrypted       = true

  lifecycle_policy { transition_to_ia                    = "AFTER_30_DAYS" }
  lifecycle_policy { transition_to_archive               = "AFTER_90_DAYS" }
  lifecycle_policy { transition_to_primary_storage_class = "AFTER_1_ACCESS" }
}

The retrieval cost — the catch with IA and Archive

IA and Archive are dramatically cheaper per GB stored but add a retrieval (read/write) charge per GB every time you touch a file that lives there. If your “cold” data is actually read constantly, IA can cost more than Standard. Do the arithmetic on your access pattern.

Class Storage $/GB-mo Retrieval $/GB (approx) Net winner when…
Standard $0.30 none Data is read often
Standard-IA $0.016 ~$0.01 read Data is read rarely (weeks between touches)
Archive $0.008 higher than IA Data is read very rarely (months between touches)

Worked example — a 1 TB file system, 90% of it untouched for months:

Layout Standard portion IA/Archive portion Monthly storage cost
No lifecycle (all Standard) 1,000 GB × $0.30 $300
Lifecycle → IA (900 GB cold) 100 GB × $0.30 = $30 900 GB × $0.016 = $14.40 $44.40
Lifecycle → Archive (900 GB) 100 GB × $0.30 = $30 900 GB × $0.008 = $7.20 $37.20

That is a ~85–88% storage saving for one lifecycle policy — as long as the cold data really is cold. TransitionToPrimaryStorageClass = AFTER_1_ACCESS protects you: anything that turns out to be hot gets promoted back to Standard on its first read, so you don’t pay repeated retrieval charges on data that woke up.

Access points and POSIX isolation

An access point turns one shared file system into many isolated, jailed subtrees, each with an enforced identity. This is how you host three apps on one file system without them stepping on each other, and how ECS, EKS and Lambda bind cleanly to a subdirectory.

What an access point enforces

Access point field What it does Example
POSIX user (Uid/Gid) Overrides the client’s user for all operations Uid=1000, Gid=1000 — every write is owned by 1000
Secondary GIDs Extra group memberships [2000, 2001] for shared-group access
Root directory Path Jails the mount to this subtree /app-a — client sees this as /
Creation info uid/gid/permissions to create the root dir if absent OwnerUid=1000, Permissions=0755
Enforcement POSIX identity is enforced, not advisory Client cannot escape the root dir or spoof a uid

Mount through an access point and the client is transparently confined to the root directory and acts as the configured POSIX user — regardless of what Linux user is running on the instance. Three apps, three access points, one file system, zero cross-talk:

App Access point root POSIX user Sees
App A /app-a uid/gid 1000 Only /app-a, as user 1000
App B /app-b uid/gid 2000 Only /app-b, as user 2000
Shared read-only /shared uid/gid 3000 Only /shared, as user 3000
# Create an access point that jails clients to /app-a as uid/gid 1000, creating the dir 0755
aws efs create-access-point --file-system-id fs-0abc123 \
  --posix-user 'Uid=1000,Gid=1000' \
  --root-directory 'Path=/app-a,CreationInfo={OwnerUid=1000,OwnerGid=1000,Permissions=0755}' \
  --tags Key=Name,Value=app-a-ap
resource "aws_efs_access_point" "app_a" {
  file_system_id = aws_efs_file_system.this.id
  posix_user { uid = 1000  gid = 1000 }
  root_directory {
    path = "/app-a"
    creation_info { owner_uid = 1000  owner_gid = 1000  permissions = "0755" }
  }
  tags = { Name = "app-a-ap" }
}

Why the POSIX identity solves “permission denied”

Without an access point, an NFS client mounts the file system root and its local users map straight through — so if the instance process runs as uid 1000 but the directory is owned by root (uid 0) with 0755, writes are denied. With an access point that sets Uid=1000 and owns the root dir as 1000, every operation is remapped to a user that owns the tree, and writes just work. The access point is both an isolation boundary and the cleanest fix for the classic NFS permission-denied problem.

Mount style User seen by EFS Root dir Typical result
Raw mount, process uid 1000, dir owned by root 1000 / root, root-owned 0755 Permission denied on write
Raw mount as root 0 / root Works, but no isolation, root everywhere
Access point (Uid=1000, owns /app-a) 1000 (enforced) /app-a owned by 1000 Writes succeed, app jailed to /app-a

Encryption and EFS IAM authorization

EFS gives you three independent security layers: encryption at rest (KMS), encryption in transit (TLS), and EFS IAM authorization (an IAM policy gating who may mount and write). Use all three in production.

Encryption at rest and in transit

Layer How When decided Notes
At rest KMS key (aws/elasticfilesystem or a CMK) At creation only — cannot change later On by default for new file systems; transparent
In transit TLS 1.2 via amazon-efs-utils (stunnel) Per mount (-o tls) Wraps NFS/2049; no extra port; small CPU cost
Key choice AWS-managed vs customer-managed CMK At creation CMK for custom key policy, cross-account, audit

Encryption at rest is a launch-time, one-way property just like EBS: you choose it (and the KMS key) when you create the file system and you cannot toggle it afterward — to change it you create a new file system and copy the data. Encryption in transit is a per-mount option (-o tls with amazon-efs-utils), which routes NFS through a local stunnel TLS tunnel to the mount target — no extra security-group port, just TCP 2049 wrapped in TLS.

# Create an encrypted file system with a customer-managed KMS key
aws efs create-file-system \
  --encrypted --kms-key-id alias/efs-cmk \
  --performance-mode generalPurpose --throughput-mode elastic \
  --tags Key=Name,Value=app-shared

EFS IAM authorization

Beyond network reachability (the security group) and POSIX (the access point), EFS IAM authorization gates the mount itself with an IAM policy — so even a client on the right network with the right SG cannot mount unless its role is allowed. It uses a file system policy (resource policy on the file system) and/or identity policies with these actions:

IAM action Grants Typical use
elasticfilesystem:ClientMount Permission to mount (read) Read-only clients
elasticfilesystem:ClientWrite Permission to write Read/write clients
elasticfilesystem:ClientRootAccess Permission to act as root (uid 0) Rarely — admin/setup only
elasticfilesystem:DescribeMountTargets Discover mount targets Tooling/automation

A common hardened file-system policy: deny any mount that isn’t using TLS, and require IAM auth. You add -o iam to the mount so the client presents its instance-role credentials.

# Mount using TLS AND IAM authorization (client presents its instance-role identity)
sudo mount -t efs -o tls,iam fs-0abc123:/ /mnt/efs
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Deny",
    "Principal": { "AWS": "*" },
    "Action": "*",
    "Resource": "arn:aws:elasticfilesystem:us-east-1:111122223333:file-system/fs-0abc123",
    "Condition": { "Bool": { "aws:SecureTransport": "false" } }
  }]
}
Control Question it answers Mechanism
Security group Can packets reach the mount target? Inbound TCP 2049 from client SG
EFS IAM auth Is this principal allowed to mount/write? ClientMount/ClientWrite/ClientRootAccess
Access point POSIX What identity + subtree does it get? Enforced uid/gid + root directory
TLS in transit Is the data encrypted on the wire? -o tls (stunnel)
KMS at rest Is the data encrypted on disk? Encryption at creation with a KMS key

Mounting from EC2, ECS/EKS and Lambda

The whole point of EFS is that many different kinds of compute mount the same tree. Each has its own mechanics.

From EC2 — amazon-efs-utils and /etc/fstab

The recommended client is amazon-efs-utils, which adds the mount -t efs helper, automatic DNS to the AZ-local mount target, TLS (via stunnel), and IAM support. You can also use the stock Linux NFS client, but you lose TLS/IAM convenience.

Client Mount command Gets you Trade-off
amazon-efs-utils mount -t efs -o tls fs-…:/ /mnt/efs TLS, IAM, AZ-aware DNS, access-point option Install the package (yum/apt)
Stock NFS client mount -t nfs4 -o nfsvers=4.1,… <dns>:/ /mnt Works everywhere No TLS/IAM helper; more flags
# Amazon Linux 2023 / 2:
sudo yum install -y amazon-efs-utils            # (Ubuntu: build/install amazon-efs-utils)
sudo mkdir -p /mnt/efs
sudo mount -t efs -o tls fs-0abc123:/ /mnt/efs   # TLS in transit
# Mount THROUGH an access point (jailed + POSIX-enforced):
sudo mount -t efs -o tls,accesspoint=fsap-0aaa111 fs-0abc123:/ /mnt/app-a
df -h /mnt/efs                                    # shows the EFS mount

Persist across reboot with /etc/fstab. The two options that matter are _netdev (wait for the network before mounting — EFS is a network filesystem) and tls:

fstab field Value (EFS) Meaning
1. File system fs-0abc123:/ (or fs-…:/ + accesspoint=) The EFS DNS/id and export path
2. Mount point /mnt/efs Where to mount
3. Type efs Uses the amazon-efs-utils helper
4. Options _netdev,tls (add ,iam, ,accesspoint=fsap-…) _netdev waits for network; tls encrypts
5. Dump 0 Legacy
6. Pass 0 Don’t fsck a network FS
# /etc/fstab line — TLS, network-aware, via an access point
echo "fs-0abc123 /mnt/app-a efs _netdev,tls,accesspoint=fsap-0aaa111 0 0" | sudo tee -a /etc/fstab
sudo mount -a          # test the line NOW, before any reboot

⚠️ _netdev is not optional. Without it, the OS may try to mount EFS before the network is up at boot, the mount fails, and (depending on the distro) boot can stall — the same class of failure as the EBS nofail/fstab boot-hang, but caused by the network not being ready. Always include _netdev, and always run sudo mount -a to test before you reboot.

From ECS and Fargate — task volumes

ECS mounts EFS through a volume in the task definition with an efsVolumeConfiguration; the container references it with a mount point. Fargate supports EFS natively (platform version 1.4+).

ECS volume field Value Purpose
fileSystemId fs-0abc123 Which file system
transitEncryption ENABLED TLS in transit (recommended)
authorizationConfig.accessPointId fsap-0aaa111 Bind to an access point (isolation)
authorizationConfig.iam ENABLED Use the task role for EFS IAM auth
rootDirectory / (or a path, if no AP) Subtree to mount (omit when using an AP)
{
  "volumes": [{
    "name": "shared",
    "efsVolumeConfiguration": {
      "fileSystemId": "fs-0abc123",
      "transitEncryption": "ENABLED",
      "authorizationConfig": { "accessPointId": "fsap-0aaa111", "iam": "ENABLED" }
    }
  }],
  "containerDefinitions": [{
    "name": "app",
    "mountPoints": [{ "sourceVolume": "shared", "containerPath": "/data" }]
  }]
}

From EKS — the EFS CSI driver

Kubernetes mounts EFS through the AWS EFS CSI driver, which supports ReadWriteMany (the reason to use EFS over EBS in k8s — EBS is ReadWriteOnce). You install the driver, define a StorageClass (often pointing at a file system with dynamic access-point provisioning), and claim it with a PVC.

EKS/EFS piece What it is Notes
EFS CSI driver Add-on that speaks CSI to EFS Install via EKS add-on or Helm; needs an IRSA role
StorageClass provisioner: efs.csi.aws.com provisioningMode: efs-ap dynamically makes access points
PV / PVC Bind pods to the file system accessModes: ReadWriteMany — the key capability
IRSA role IAM for the driver elasticfilesystem:* scoped actions
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata: { name: efs-sc }
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap          # dynamically create an access point per PVC
  fileSystemId: fs-0abc123
  directoryPerms: "0755"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: shared-pvc }
spec:
  accessModes: ["ReadWriteMany"]     # many pods mount it at once
  storageClassName: efs-sc
  resources: { requests: { storage: 5Gi } }   # size is nominal — EFS is elastic

From Lambda — VPC + access point

A Lambda function can mount EFS at a local path, so serverless code shares files with EC2/containers. Two hard requirements: the function must be in the VPC (attached to subnets that have mount targets), and it mounts through an access point at a LocalMountPath under /mnt.

Lambda EFS requirement Detail
VPC config Function attached to subnets with mount targets + a security group
Access point FileSystemConfig.Arn = the access point ARN (not the raw FS)
Local mount path LocalMountPath must start with /mnt/ (e.g. /mnt/efs)
Security group Function SG allowed to reach the mount target SG on 2049
Permissions Execution role needs EFS + VPC ENI permissions
aws lambda update-function-configuration --function-name my-fn \
  --vpc-config 'SubnetIds=subnet-a,subnet-b,SecurityGroupIds=sg-clients' \
  --file-system-configs 'Arn=arn:aws:elasticfilesystem:us-east-1:111122223333:access-point/fsap-0aaa111,LocalMountPath=/mnt/efs'
resource "aws_lambda_function" "fn" {
  function_name = "my-fn"
  # … handler/runtime/role …
  vpc_config { subnet_ids = [var.subnet_a, var.subnet_b]  security_group_ids = [aws_security_group.clients.id] }
  file_system_config {
    arn              = aws_efs_access_point.app_a.arn   # the access point, not the FS
    local_mount_path = "/mnt/efs"
  }
  depends_on = [aws_efs_mount_target.a, aws_efs_mount_target.b]  # MTs must exist first
}

EFS vs EBS vs FSx vs S3 — choosing the right storage

The most common real question is not “how do I use EFS” but “should this be EFS at all.” The decision table:

If you need… Choose Why
Shared POSIX files across many Linux instances/AZs EFS The only AWS-native multi-attach elastic NFS
A boot disk or single-node database volume EBS Lowest latency block, single-attach
Object storage / static assets / data lake S3 Cheapest, infinite, HTTP — not a filesystem
Ephemeral scratch at max speed Instance store Local NVMe; lost on stop
Windows file shares (SMB, AD) FSx for Windows File Server Native SMB + Active Directory
HPC / ML highest throughput, POSIX FSx for Lustre Massively parallel, S3-linked
NetApp ONTAP features (snapshots, dedup, multi-protocol) FSx for NetApp ONTAP ONTAP on AWS; NFS + SMB + iSCSI
High-performance ZFS (snapshots, NFS) FSx for OpenZFS Low-latency ZFS over NFS
ReadWriteMany volumes for Kubernetes pods EFS (CSI driver) EBS CSI is ReadWriteOnce only

The FSx family, side by side — EFS is Linux/NFS/elastic; FSx is the specialized-protocol/performance answer:

Service Protocol OS focus Elastic capacity Headline strength
EFS NFSv4.1 Linux Yes (auto grow/shrink) Simple, serverless, multi-AZ shared NFS
FSx for Windows SMB Windows Provisioned AD-integrated Windows shares
FSx for Lustre Lustre (POSIX) Linux/HPC Provisioned Extreme parallel throughput; S3 integration
FSx for NetApp ONTAP NFS + SMB + iSCSI Multi Provisioned + tiering ONTAP feature set, multi-protocol
FSx for OpenZFS NFS Linux Provisioned ZFS snapshots/clones, low latency
Dimension EFS EBS S3
Shape File (NFS) Block (disk) Object (HTTP)
Multi-attach Yes (thousands) No (special-case 16 with io2) Yes (API)
Scope Region (multi-AZ) One AZ Region
Capacity model Elastic, pay-per-use Provisioned size Pay-per-use, infinite
Mountable filesystem Yes Yes No
Best at Shared files across a fleet Low-latency single-node disk Cheap durable objects

Backup with AWS Backup

EFS integrates with AWS Backup for centralized, policy-driven, point-in-time backups (there is no separate “EFS snapshot” API — AWS Backup is the mechanism). You define a backup plan (schedule + retention + optional cross-Region/cross-account copy) and assign the file system by tag or ARN.

AWS Backup for EFS Detail
Mechanism AWS Backup plan → backup vault (no native EFS snapshot API)
What’s captured Point-in-time recovery point of the whole file system
Restore To a new or the same file system (full or item-level)
Cross-Region / account Copy recovery points for DR / ransomware isolation
Automatic backups New EFS file systems get a default daily AWS Backup plan (opt-out)
Vault Lock Immutable retention for compliance
resource "aws_backup_plan" "efs" {
  name = "efs-daily"
  rule {
    rule_name         = "daily-35d"
    target_vault_name = aws_backup_vault.main.name
    schedule          = "cron(0 3 * * ? *)"
    lifecycle { delete_after = 35 }
  }
}
resource "aws_backup_selection" "efs" {
  name         = "efs-selection"
  plan_id      = aws_backup_plan.efs.id
  iam_role_arn = aws_iam_role.backup.arn
  resources    = [aws_efs_file_system.this.arn]
}

Architecture at a glance

The diagram reads left to right and shows the whole shared-storage picture on one canvas. On the left, three different kinds of client mount the same file tree at the same time: an EC2 instance in us-east-1a, an EC2 instance in us-east-1b, and a Lambda function in the VPC — proof that EFS is shared, concurrent and cross-AZ in a way EBS can never be. Each client reaches the file system through a mount target — one ENI per AZ (badge 3) whose security group must allow inbound NFS on TCP 2049; get that rule wrong and the mount hangs. Clients mount through an access point (badge 4) that pins a POSIX uid/gid and jails them to a root directory, so apps stay isolated on one file system. Behind the mount targets sits the file system itself (badge 5): a regional, multi-AZ, elastic NFSv4.1 service encrypted at rest with KMS and in transit with TLS, where a byte written by the AZ-a instance is instantly readable by the AZ-b instance and the Lambda. Finally, a lifecycle policy (badge 6) silently tiers files that go cold from Standard to Infrequent Access and then Archive, cutting the storage bill by up to ~90% while keeping every file in the same path.

Left-to-right architecture of Amazon EFS shared file storage: an EC2 instance in Availability Zone us-east-1a, an EC2 instance in us-east-1b, and a VPC-attached Lambda function all mount the same NFSv4.1 file tree simultaneously; each reaches the file system through a per-AZ mount target, which is an elastic network interface in that AZ's subnet whose security group must allow inbound NFS on TCP 2049; clients mount through an access point that enforces a POSIX uid/gid of 1000 and jails them to the /app root directory; the file system is a regional, multi-AZ, elastic Amazon EFS resource encrypted at rest with a KMS key and in transit with TLS; and a lifecycle policy transitions files not accessed for 30 and 90 days from the Standard storage class to Infrequent Access and then Archive; six numbered badges mark mounting from EC2 with amazon-efs-utils and TLS, the Lambda VPC-plus-access-point mount, the mount-target security group allowing 2049, the access point POSIX enforcement, the elastic multi-AZ file system shared by thousands of clients, and lifecycle tiering to IA and Archive.

The one-line summary of what each stage does — the mental index for the rest of the article:

Stage The component The one thing to remember
Clients EC2 (2 AZs) + Lambda Many clients, all AZs, mount the same tree at once
Reach it Mount target per AZ (ENI) Its SG must allow TCP 2049 from clients
Isolate Access point (uid/gid + root) POSIX identity is enforced, per-app jail
Store Elastic multi-AZ NFSv4.1 FS Encrypted at rest (KMS) + in transit (TLS)
Save Lifecycle → IA → Archive Cold files auto-tier for up to ~90% less

Real-world scenario

Brightleaf Media, a 60-person digital publisher, ran WordPress for a network of magazine sites on three EC2 instances behind an Application Load Balancer. Each instance kept its own copy of wp-content/uploads on a local EBS volume, and “syncing” them was a nightly rsync cron that everyone hated. The symptoms were constant: an editor uploaded a hero image, it landed on instance 2, and readers whose session hit instance 1 or 3 saw a broken image until the next night’s sync. Plugin installs had to be done three times. When Auto Scaling added a fourth instance during a traffic spike, it came up with an empty uploads directory and served 404s for every image until someone noticed.

The fix was to make the uploads directory shared, and that is exactly EFS’s job. They created a General Purpose, Elastic-throughput, encrypted EFS file system, added mount targets in all three AZs the ASG used (each with a security group allowing 2049 from the web-tier SG only), and created an access point rooted at /uploads enforcing the www-data POSIX identity (uid/gid 33) so WordPress could write without a permission fight. They baked the mount into the launch template’s user-data — /etc/fstab line fs-…: /var/www/html/wp-content/uploads efs _netdev,tls,accesspoint=fsap-… 0 0 — so every instance the ASG launches, in any AZ, mounts the same uploads tree at boot. The nightly rsync was deleted.

Two things surprised them. First, they had initially left the file system on Bursting throughput (an older console default), and after a week the media-heavy site slowed noticeably during traffic peaks — BurstCreditBalance in CloudWatch was trending to zero, because the file system only held ~40 GB, giving a baseline of 40 × 50 KB/s = 2 MB/s, nowhere near enough for concurrent image serving. Switching to Elastic with one update-file-system call — no downtime, no remount — removed the throttling entirely and they stopped thinking about throughput. Second, the FinOps review a quarter later flagged that the file system had grown to 1.2 TB, dominated by years of old article images almost never re-requested. They enabled lifecycle management (TransitionToIA AFTER_30_DAYS, TransitionToArchive AFTER_90_DAYS, TransitionToPrimaryStorageClass AFTER_1_ACCESS); within a month ~85% of the data had moved to IA/Archive and the EFS storage line dropped from about $360/month to roughly $60/month, with any image that got re-featured automatically promoted back to Standard on its first read.

The before/after captured it:

Aspect Before (EBS-per-instance + rsync) After (shared EFS)
Uploads consistency Eventually consistent (nightly rsync) Instant — one shared tree
New ASG instance Empty uploads → 404s until sync Mounts the shared tree at boot
Plugin/media install Repeated on every instance Once, visible everywhere
Throughput (n/a) then Bursting → throttled at 2 MB/s Elastic — no throttling
Permissions chmod fights per instance Access point enforces www-data
Storage cost (1.2 TB) ~$360→$60/mo via lifecycle to IA/Archive
Cross-AZ resilience Per-instance, per-AZ copies Multi-AZ file system, survives an AZ loss

The lesson the platform lead wrote up: “Every hard part of running WordPress on more than one box was really just ‘these machines can’t see the same files.’ EFS made the uploads directory one thing instead of three, and the two gotchas — Bursting throttling and no lifecycle — were each a one-line fix once we knew to look.”

Advantages and disadvantages

The honest two-column view of building on EFS:

Advantages of EFS Disadvantages / what to watch
Shared — thousands of clients, all AZs, one tree Higher latency than local/EBS block (it’s NFS over the network)
Elastic — grows/shrinks automatically, no provisioning Standard is pricey per GB ($0.30) if you skip lifecycle
Multi-AZ durable (Standard) — survives an AZ loss One Zone is cheaper but single-AZ (can lose data)
Fully managed NFS — no servers to patch or scale Bursting throughput throttles small file systems
POSIX semantics — legacy apps and CMSes “just work” Not for high-IOPS single-node databases (use EBS)
Access points give clean per-app isolation Mount target SG (2049) misconfig = silent hang
Native EC2 / ECS / EKS (RWX) / Lambda integration Performance mode is permanent; encryption-at-rest is permanent
TLS + KMS + EFS IAM = defense in depth Cross-AZ mounts add latency + data-transfer cost

When each side matters: for the default case — a shared directory across a fleet, a CMS behind a load balancer, ReadWriteMany for containers, a shared ML dataset — the advantages dominate and EFS is the obvious right tool. The disadvantages bite at the edges: latency-sensitive single-node databases (put those on EBS or io2), cost hygiene on Standard-only file systems (enable lifecycle), the Bursting throttle (use Elastic), and the 2049 security-group trap (which the troubleshooting playbook below exists to kill). Every one is avoidable with the practices in this article.

Hands-on lab

You’ll create a General Purpose, Elastic-throughput, encrypted EFS file system, add mount targets in two AZs behind an NFS security group, mount it on two EC2 instances in different AZs, write a file on one and read it on the other (the proof that it’s shared), create an access point, enable lifecycle to IA, then tear everything down. Everything is aws CLI first; a Terraform version follows. Region is us-east-1; you have a VPC with subnets in us-east-1a and us-east-1b and one instance in each. Replace IDs with yours.

⚠️ Cost note: A small file system holding a few files for a lab hour costs a rounding error, and the first 5 GB of Standard storage is free for 12 months. The things that bill if you forget them: leftover Provisioned throughput, a large file system with no lifecycle, and the two EC2 instances (their own charge). Do the teardown at the end.

Step 1 — Create security groups (client + mount target)

VPC=vpc-0yourvpc
# SG for the clients (attach to your instances)
CLIENTS=$(aws ec2 create-security-group --group-name efs-clients \
  --description "EFS client SG" --vpc-id $VPC --query GroupId --output text)
# SG for the mount targets, allowing NFS 2049 FROM the client SG
MTSG=$(aws ec2 create-security-group --group-name efs-mt \
  --description "EFS mount target SG" --vpc-id $VPC --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id $MTSG \
  --protocol tcp --port 2049 --source-group $CLIENTS
echo "clients=$CLIENTS  mount-target-sg=$MTSG"

Step 2 — Create the file system (GP, Elastic, encrypted)

FS=$(aws efs create-file-system \
  --performance-mode generalPurpose --throughput-mode elastic --encrypted \
  --tags Key=Name,Value=lab-efs \
  --query FileSystemId --output text)
aws efs describe-file-systems --file-system-id $FS \
  --query 'FileSystems[0].LifeCycleState' --output text     # wait for "available"
echo "FileSystem: $FS"

Step 3 — Create a mount target in EACH AZ

SUBNET_A=subnet-0a_in_us_east_1a
SUBNET_B=subnet-0b_in_us_east_1b
MTA=$(aws efs create-mount-target --file-system-id $FS \
  --subnet-id $SUBNET_A --security-groups $MTSG --query MountTargetId --output text)
MTB=$(aws efs create-mount-target --file-system-id $FS \
  --subnet-id $SUBNET_B --security-groups $MTSG --query MountTargetId --output text)
# Wait until BOTH are "available"
aws efs describe-mount-targets --file-system-id $FS \
  --query 'MountTargets[].[MountTargetId,AvailabilityZoneName,LifeCycleState]' --output text

Step 4 — Mount on instance A (in us-east-1a) and write a file

Attach the efs-clients SG to both instances first, then SSH/Session Manager into instance A:

sudo yum install -y amazon-efs-utils          # Amazon Linux
sudo mkdir -p /mnt/efs
sudo mount -t efs -o tls $FS:/ /mnt/efs        # replace $FS with fs-...
df -h /mnt/efs                                  # confirms the mount
echo "written on instance A in us-east-1a at $(date)" | sudo tee /mnt/efs/proof.txt

Step 5 — Mount on instance B (in us-east-1b) and READ the same file

SSH/Session Manager into instance B (different AZ):

sudo yum install -y amazon-efs-utils
sudo mkdir -p /mnt/efs
sudo mount -t efs -o tls fs-0abc123:/ /mnt/efs
cat /mnt/efs/proof.txt      # → "written on instance A in us-east-1a at ..."

Seeing instance A’s file on instance B, across two Availability Zones, instantly — with no sync — is the entire point of EFS.

Step 6 — Create an access point (POSIX + jailed root dir)

AP=$(aws efs create-access-point --file-system-id $FS \
  --posix-user 'Uid=1000,Gid=1000' \
  --root-directory 'Path=/app-a,CreationInfo={OwnerUid=1000,OwnerGid=1000,Permissions=0755}' \
  --tags Key=Name,Value=lab-ap --query AccessPointId --output text)
# Mount THROUGH it — the client is jailed to /app-a as uid 1000
sudo mount -t efs -o tls,accesspoint=$AP $FS:/ /mnt/app-a

Step 7 — Enable lifecycle management (transition to IA)

aws efs put-lifecycle-configuration --file-system-id $FS \
  --lifecycle-policies \
    '{"TransitionToIA":"AFTER_30_DAYS"}' \
    '{"TransitionToPrimaryStorageClass":"AFTER_1_ACCESS"}'
aws efs describe-lifecycle-configuration --file-system-id $FS   # verify the policy

Step 8 — Persist the mount across reboot (fstab)

echo "$FS /mnt/efs efs _netdev,tls 0 0" | sudo tee -a /etc/fstab
sudo umount /mnt/efs && sudo mount -a       # TEST the line before rebooting
df -h /mnt/efs                              # still mounted → line is correct

Step 9 — Teardown (do this — some parts bill)

# On each instance: unmount and remove the fstab line
sudo umount /mnt/efs /mnt/app-a 2>/dev/null
sudo sed -i "\#$FS /mnt/efs#d" /etc/fstab
# AWS: delete access point, mount targets, then the file system
aws efs delete-access-point --access-point-id $AP
aws efs delete-mount-target --mount-target-id $MTA
aws efs delete-mount-target --mount-target-id $MTB
# wait until mount targets are gone, THEN delete the file system
aws efs delete-file-system --file-system-id $FS
# finally the SGs (after nothing references them)
aws ec2 delete-security-group --group-id $MTSG
aws ec2 delete-security-group --group-id $CLIENTS

Confirm each stage before moving on — most lab failures are a skipped checkpoint:

Checkpoint Command Pass looks like
File system ready aws efs describe-file-systems --file-system-id $FS LifeCycleState: available
Mount targets in 2 AZs aws efs describe-mount-targets --file-system-id $FS Two rows, both available, different AZs
SG allows 2049 aws ec2 describe-security-groups --group-ids $MTSG Ingress TCP 2049 from $CLIENTS
Mounted (A) df -h /mnt/efs (instance A) EFS mount shown
Shared read (B) cat /mnt/efs/proof.txt (instance B) Instance A’s line appears
Access point aws efs describe-access-points --file-system-id $FS AP with /app-a + uid 1000
Lifecycle set aws efs describe-lifecycle-configuration --file-system-id $FS TransitionToIA: AFTER_30_DAYS

And the Terraform equivalent for the whole core (with terraform destroy teardown):

provider "aws" { region = "us-east-1" }

resource "aws_security_group" "clients" {
  name = "efs-clients"  description = "EFS clients"  vpc_id = var.vpc_id
  egress { from_port = 0  to_port = 0  protocol = "-1"  cidr_blocks = ["0.0.0.0/0"] }
}

resource "aws_security_group" "efs_mt" {
  name = "efs-mt"  description = "EFS mount targets"  vpc_id = var.vpc_id
  ingress {
    from_port = 2049  to_port = 2049  protocol = "tcp"
    security_groups = [aws_security_group.clients.id]   # NFS from clients only
  }
}

resource "aws_efs_file_system" "this" {
  creation_token   = "lab-efs"
  performance_mode = "generalPurpose"
  throughput_mode  = "elastic"
  encrypted        = true
  lifecycle_policy { transition_to_ia                    = "AFTER_30_DAYS" }
  lifecycle_policy { transition_to_primary_storage_class = "AFTER_1_ACCESS" }
  tags = { Name = "lab-efs" }
}

resource "aws_efs_mount_target" "a" {
  file_system_id  = aws_efs_file_system.this.id
  subnet_id       = var.subnet_a          # us-east-1a
  security_groups = [aws_security_group.efs_mt.id]
}
resource "aws_efs_mount_target" "b" {
  file_system_id  = aws_efs_file_system.this.id
  subnet_id       = var.subnet_b          # us-east-1b
  security_groups = [aws_security_group.efs_mt.id]
}

resource "aws_efs_access_point" "app_a" {
  file_system_id = aws_efs_file_system.this.id
  posix_user { uid = 1000  gid = 1000 }
  root_directory {
    path = "/app-a"
    creation_info { owner_uid = 1000  owner_gid = 1000  permissions = "0755" }
  }
  tags = { Name = "lab-ap" }
}

output "file_system_id" { value = aws_efs_file_system.this.id }
output "dns_name"       { value = aws_efs_file_system.this.dns_name }
output "access_point"   { value = aws_efs_access_point.app_a.id }

Common mistakes & troubleshooting

This is the section you’ll return to mid-incident. EFS failures are quiet: a bad security group doesn’t error, it hangs. The playbook first — symptom, root cause, the exact command or console path to confirm, and the fix — then references and the two nastiest failures in prose.

# Symptom Root cause Confirm (exact command / console path) Fix
1 mount hangs ~60s then times out Mount target SG doesn’t allow 2049 from the client nc -vz <mt-ip> 2049 fails; check MT SG ingress Add inbound TCP 2049 from the client SG on the mount target SG
2 Mount hangs only from some instances No mount target in that instance’s AZ aws efs describe-mount-targets lists AZs; compare to instance AZ Create a mount target in every AZ you run in
3 Mount fails: name won’t resolve VPC DNS resolution/hostnames disabled aws ec2 describe-vpc-attribute --attribute enableDnsSupport Enable enableDnsSupport and enableDnsHostnames, or mount the MT IP
4 Permission denied writing to the share Process uid ≠ dir owner; root-owned dir over NFS ls -ln /mnt/efs shows owner uid; compare to your process Mount via an access point with a matching POSIX uid/gid, or chown the dir
5 Writes as root map to nobody NFS root-squash without ClientRootAccess/AP id on the write; file owner shows nobody/65534 Use an access point (enforced uid) or grant ClientRootAccess via EFS IAM
6 App fast in test, slow in prod Bursting credits drained on a small FS CloudWatch BurstCreditBalance trending to 0 update-file-system --throughput-mode elastic
7 Throughput capped even with credits Hitting the file system’s PercentIOLimit (GP mode) CloudWatch PercentIOLimit near 100% Move to Elastic throughput; do not reach for Max I/O
8 TLS mount fails / stunnel error amazon-efs-utils/stunnel missing or blocked mount -t efs -o tls … errors; which stunnel Install/upgrade amazon-efs-utils; ensure the helper’s efs-proxy/stunnel runs
9 Lambda mount: EFSMountFailure/timeout Function not in VPC, or not via access point, or SG blocks 2049 Function VPC config; FileSystemConfig ARN Put fn in subnets with mount targets, use the access point ARN, allow 2049
10 AccessDenied on mount despite open SG EFS IAM file-system policy denies the principal File system policy; CloudTrail ClientMount deny Grant elasticfilesystem:ClientMount/ClientWrite to the role; add -o iam
11 Boot stalls after adding EFS to fstab Missing _netdev — mount tried before network EC2 serial console shows it hung on mount Add _netdev (and tls); test with sudo mount -a before rebooting
12 Bill higher than expected No lifecycle — all data on Standard ($0.30/GB) describe-lifecycle-configuration empty; CloudWatch StorageBytes Standard Enable lifecycle to IA/Archive; check retrieval vs storage math
13 Can’t delete the file system Mount targets (or access points) still exist describe-mount-targets returns rows Delete access points + all mount targets first, then the FS
14 Cross-AZ mount slower + costs more Client resolving a mount target in a different AZ Mount IP’s AZ ≠ instance AZ Ensure a mount target exists in the client’s own AZ (DNS picks local)
15 One Zone file system unmountable from other AZs One Zone lives in a single AZ; only one MT describe-file-systems … AvailabilityZoneName set Use Standard for multi-AZ, or run clients in that one AZ
16 Data on a One Zone FS lost after AZ event One Zone stores data in one AZ only Storage class = One Zone (single-AZ) Use Standard (multi-AZ) for anything you can’t rebuild; back up with AWS Backup

The EFS error/status reference — the strings and states you’ll actually see:

Status / error Where Meaning Fix
creatingavailable file system / mount target Provisioning, then ready Wait for available before mounting
mount.nfs4: Connection timed out client mount SG blocks 2049, or no MT in this AZ Open 2049; add a mount target in the AZ
mount.nfs4: access denied by server client mount EFS IAM policy / export denies you Grant ClientMount/ClientWrite; check FS policy
Permission denied (write) app / shell POSIX uid mismatch / root-squash Access point with matching uid, or chown
EFSMountFailureException Lambda invoke VPC/access-point/SG misconfig VPC + access point ARN + 2049
FileSystemInUse delete-file-system Mount targets still attached Delete MTs (and APs) first
MountTargetConflict create-mount-target Already a mount target in that AZ/subnet One MT per AZ — reuse it
BurstCreditBalance → 0 CloudWatch Bursting mode exhausted credits Switch to Elastic throughput
PercentIOLimit ~100% CloudWatch General Purpose IOPS ceiling Elastic throughput (not Max I/O)
stunnel/efs-proxy failed client log TLS helper not running Reinstall/upgrade amazon-efs-utils

And the fast decision table — observation to likely cause:

If you see… It’s probably… Do this
Mount hangs then times out SG 2049 blocked, or no MT in this AZ Open 2049 from client SG; add MT in the AZ
Works from AZ-a, hangs from AZ-b Missing mount target in AZ-b Create the AZ-b mount target
Permission denied on write uid mismatch / root-squash Mount via access point (enforced uid)
Fast in demo, slow in prod Bursting credits drained Switch to Elastic throughput
Lambda can’t mount Not in VPC / not via access point VPC config + access point ARN + 2049
Surprise storage bill No lifecycle (all Standard) Enable lifecycle to IA/Archive
Can’t delete file system Mount targets/APs still exist Delete APs + MTs first

Two failures deserve emphasis because they cause the most wasted hours. The 2049 security-group hang (rows 1–2) is the signature EFS incident, and it is nasty precisely because it produces no error — the mount command sits silent for about 60 seconds and then returns Connection timed out, giving you nothing to search for. The diagnosis is always the same two questions: is there a mount target in this instance’s Availability Zone? (aws efs describe-mount-targets and compare AZs) and does the mount target’s security group allow inbound TCP 2049 from this client? (nc -vz <mount-target-ip> 2049 — a fast success or a hang tells you instantly). Ninety percent of “EFS won’t mount” is one of those two, and the least-privilege fix is a single ingress rule allowing 2049 from the client security group. The second is the Bursting throttle (row 6): it is invisible in every demo because a new file system starts with a full credit balance and flies, then a week into production the credits drain and throughput collapses to 50 KB/s × (GB stored) with no error logged anywhere — you find it only by looking at the BurstCreditBalance CloudWatch metric trending to zero. The permanent fix is to stop thinking about throughput at all: switch to Elastic mode, which is why AWS made it the default for new file systems.

Best practices

Security notes

EFS security is defense in depth across the network, the protocol, the identity, and the data. The posture, row by row:

Concern Weak default Least-privilege / hardened control
Network reachability MT SG open to the VPC/0.0.0.0/0 2049 only from the client SG (sg-reference)
Data in transit Plaintext NFS TLS (-o tls); deny non-TLS via aws:SecureTransport
Data at rest (New FS: encrypted by default) KMS CMK with a scoped key policy for audit/cross-account
Who may mount Anyone on the network EFS IAM: ClientMount/ClientWrite per role
Root on the share Root-squash or full root Access point enforces a non-root uid; grant ClientRootAccess only when required
App isolation Everyone mounts / Access point per app with a jailed root dir
Blast radius One file system for everything Separate file systems / access points per environment
Audit None CloudTrail on EFS API + ClientMount events; KMS Decrypt logging
Backups / recovery None or manual AWS Backup plan + Vault Lock; cross-account copy

Two points to emphasize. First, the security group is your primary access control at the network layer, and 2049-from-anywhere is a real exposure. Any principal that can reach the mount target on 2049 can attempt a mount; scope the mount-target SG to only the client security group, and layer EFS IAM so that even a reachable client must hold ClientMount to succeed. Second, encryption in transit is free, so there’s no excuse to skip it-o tls wraps NFS through a local stunnel on the same 2049 port, adds no security-group rules, and a file-system policy with a "aws:SecureTransport": "false" deny makes it mandatory. Combine at-rest KMS, in-transit TLS, IAM-gated mounts, and access-point POSIX enforcement and a leaked network path alone gets an attacker nothing.

Cost & sizing

EFS bills for four things: stored data (per GB-month, by storage class), throughput (with Elastic, per GB read/written; with Provisioned, per MB/s-month), requests/retrieval on IA and Archive (per GB accessed), and backups (AWS Backup storage). Unlike EBS you never pay for “provisioned but empty” capacity — you pay for the bytes you actually store. The drivers, with us-east-1 rates:

Cost component Rate (us-east-1, approx) Notes
Standard storage $0.30/GB-mo Multi-AZ; the hot tier
Standard-IA storage $0.016/GB-mo + per-GB retrieval on access
Archive storage $0.008/GB-mo Coldest; higher retrieval, kept online
One Zone storage $0.16/GB-mo Single-AZ; ~47% cheaper than Standard
One Zone-IA $0.0133/GB-mo Single-AZ cold
IA/Archive retrieval ~$0.01/GB (IA read) Charged each time you access tiered data
Elastic throughput ~$0.03/GB read, ~$0.06/GB write Pay per data moved; no provisioning
Provisioned throughput ~$6.00/MB/s-mo Above what size-based bursting gives
AWS Backup storage per GB-mo of recovery points Separate line; set retention
Cross-AZ data transfer per GB Mounting a mount target in another AZ

Rough anchors: a 100 GB all-Standard file system is $30/month (~₹2,580 at ~₹86/$); enable lifecycle so 80 GB goes to IA and it drops to 20 × $0.30 + 80 × $0.016 = $7.28/month. A 1 TB Standard file system is $300/month; the same TB with 90% on Archive is about $37/month — the lifecycle policy is worth 8× here. The free tier includes 5 GB of Standard storage for 12 months. The three biggest wastes, in order: no lifecycle (paying $0.30 for cold data that could be $0.016 or $0.008), Provisioned throughput left on when Elastic would be cheaper for a spiky workload, and abandoned file systems nobody deleted (you pay for every stored byte forever). Sizing discipline is simpler than EBS because there is no size to provision: start on Elastic + General Purpose, turn lifecycle on from day one, and let the file system grow and shrink itself.

Interview & exam questions

Q1. What is the fundamental difference between EFS and EBS? EBS is block storage that attaches to one instance in one Availability Zone; EFS is a file system (NFSv4.1) that thousands of clients across all AZs mount simultaneously and that grows/shrinks elastically. Use EBS for a single-node disk (boot, database); use EFS for shared files across a fleet. (CLF-C02, SAA-C03)

Q2. Why does my EFS mount hang for 60 seconds and then time out? The mount target’s security group isn’t allowing inbound TCP 2049 from the client, or there is no mount target in the client’s Availability Zone. Confirm with nc -vz <mount-target-ip> 2049 and aws efs describe-mount-targets; fix by opening 2049 from the client SG and ensuring a mount target exists in every AZ you run in. (SAA-C03, SOA-C02)

Q3. What is a mount target and how many do you need? A mount target is an elastic network interface placed in a subnet, giving the file system an IP and DNS endpoint in that Availability Zone, with a security group. You create one per AZ you want to mount from; clients resolve the file system DNS to the mount target in their own AZ. (SAA-C03)

Q4. A database was fast in a load test but throttles in production on EFS. Why? The file system is on Bursting throughput, whose baseline is only 50 KB/s per GB stored. A new file system starts with a credit balance (fast in the test) that drains under sustained load, dropping to a tiny baseline. Switch to Elastic throughput (one update-file-system call, no downtime). (SOA-C02, SAA-C03)

Q5. What does an access point enforce, and what problem does it solve? An access point pins a POSIX user (uid/gid) and a root directory, jailing every client that mounts through it to that subtree acting as that identity — regardless of the local Linux user. It gives per-app isolation on one file system and is the cleanest fix for NFS permission-denied (the enforced uid owns the directory). (SAA-C03)

Q6. How do you encrypt EFS in transit, and what port does it use? Mount with -o tls using amazon-efs-utils, which routes NFS through a local stunnel TLS tunnel to the mount target — over the same TCP 2049 port, so no extra security-group rule is needed. You can make it mandatory with a file-system policy that denies aws:SecureTransport = false. (SCS-C02, SAA-C03)

Q7. Explain EFS storage classes and lifecycle management. Files live in Standard (multi-AZ, hot), Standard-IA/Archive (progressively colder, cheaper per GB but with retrieval charges), or the single-AZ One Zone/One Zone-IA. A lifecycle policy moves files to IA/Archive after N days without access and (optionally) back to Standard on first access — the single biggest EFS cost lever. (CLF-C02, SAA-C03)

Q8. When would you choose One Zone over Standard? When lower cost matters more than AZ resilience and the data is easily reproducible (dev/test, scratch, derived data). One Zone is ~47% cheaper but stores data in one AZ only, so it’s lost if that AZ is destroyed — never use it for data you can’t rebuild. (SAA-C03)

Q9. How does a Lambda function mount EFS? The function must be attached to the VPC (subnets that have mount targets, plus a security group allowed to reach 2049), and it mounts through an access point at a LocalMountPath under /mnt (e.g. /mnt/efs). You reference the access point ARN in the function’s FileSystemConfig, not the raw file system. (DVA-C02, SAA-C03)

Q10. Why use EFS instead of EBS for persistent volumes in EKS? EBS volumes are ReadWriteOnce (one node at a time), so pods on different nodes can’t share them. The EFS CSI driver provides ReadWriteMany volumes that many pods across many nodes mount concurrently — the right choice for shared state. (SAA-C03)

Q11. What are General Purpose and Max I/O performance modes, and which should you pick? General Purpose gives the lowest per-operation latency and is recommended for essentially every workload; Max I/O trades latency for a higher aggregate IOPS ceiling and is a legacy mode AWS steers you away from for new file systems. The mode is fixed at creation — choose General Purpose, and if you’re I/O-bound (PercentIOLimit near 100%) move to Elastic throughput, not Max I/O. (SAA-C03, SOA-C02)

Q12. How do you back up an EFS file system? Through AWS Backup — there is no native EFS snapshot API. You create a backup plan (schedule, retention, optional cross-Region/account copy) and assign the file system; new file systems get a default daily backup you can opt out of. Restore to a new or the same file system, full or item-level. (SOA-C02, SAA-C03)

Quick check

  1. You have instances in us-east-1a, 1b and 1c behind an Auto Scaling group. How many mount targets do you need, and why?
  2. Your mount -t efs command hangs and times out. What are the two things to check first?
  3. Why does a small EFS file system on Bursting throughput slow down in production but not in a demo?
  4. An app writes to the share as uid 1000 but gets “permission denied.” What’s the cleanest EFS-native fix?
  5. Name the one setting that most reduces EFS storage cost, and the option that protects you if “cold” data turns out to be hot.

Answers

  1. Three — one mount target per Availability Zone the ASG can place instances in. An instance that lands in an AZ with no mount target will hang on mount forever, and ASG placement is non-deterministic, so a missing MT shows up as intermittent failures.
  2. (a) Does the mount target’s security group allow inbound TCP 2049 from the client (test nc -vz <mt-ip> 2049)? (b) Is there a mount target in this instance’s AZ (aws efs describe-mount-targets)? Those two cover ~90% of mount hangs.
  3. Bursting baseline is 50 KB/s per GB stored, so a small file system has a tiny baseline. A new file system starts with a full burst-credit balance (fast demo); under sustained production load the credits drain and throughput falls to that tiny baseline. Fix: switch to Elastic.
  4. Create an access point with Uid=1000,Gid=1000 and a root directory owned by 1000, and mount through it (-o tls,accesspoint=fsap-…). The access point enforces the uid so the directory is owned by the writing identity — no root-squash, no chmod fight.
  5. Lifecycle management (transition idle files to IA/Archive) is the biggest cost lever; TransitionToPrimaryStorageClass = AFTER_1_ACCESS protects you by moving any file that gets read back up to Standard on first access, so hot data doesn’t pay repeated retrieval charges.

Glossary

Term Definition
EFS Elastic File System — a fully-managed, elastic, multi-AZ NFSv4.1 file system that many EC2 instances, containers and Lambda functions mount and share simultaneously.
File system The EFS resource (fs-…); regional, elastic, holding the shared POSIX directory tree.
Mount target An elastic network interface EFS places in one subnet/AZ, giving the file system a private IP, DNS endpoint and security group for clients in that AZ; one per AZ.
NFSv4.1 The Network File System protocol version clients use to mount EFS, over TCP port 2049, with POSIX semantics and byte-range locking.
Security group (mount target) The firewall on the mount target ENI; must allow inbound TCP 2049 from client security groups for a mount to succeed.
Access point A named entry into the file system that enforces a POSIX uid/gid and a root directory, giving per-app isolation and clean container/Lambda binding.
Performance mode General Purpose (lowest latency, the default) or the legacy Max I/O (higher aggregate IOPS, higher latency); fixed at file-system creation.
Throughput mode Elastic (auto-scaling, pay-per-GB — the modern default), Bursting (baseline tied to size + credits), or Provisioned (a fixed MB/s you buy).
Burst credits The bucket that funds throughput above the Bursting baseline (50 KB/s per GB); drains under sustained load on small file systems, causing throttling.
Storage class The durability/price tier a file lives in: Standard, Standard-IA, Archive (multi-AZ) or One Zone / One Zone-IA (single-AZ, cheaper, less durable).
Lifecycle management A policy that transitions files between storage classes by access age (to IA/Archive when cold, back to Standard on access) — the primary EFS cost lever.
amazon-efs-utils The AWS mount helper providing mount -t efs, TLS-in-transit via stunnel, IAM authorization, access-point mounting, and AZ-aware DNS.
EFS IAM authorization Gating mounts with IAM (elasticfilesystem:ClientMount/ClientWrite/ClientRootAccess) via a file-system policy and/or identity policy.
_netdev / tls fstab mount options for EFS: _netdev waits for the network before mounting; tls encrypts the NFS traffic in transit.
EFS CSI driver The Kubernetes driver that provisions EFS as ReadWriteMany persistent volumes so many pods across many nodes share one file system.
AWS Backup The service that backs up EFS (there is no native snapshot API): scheduled recovery points with retention and cross-Region/account copy.

Next steps

AWSEFSNFSMount TargetsAccess PointsElastic ThroughputEFS CSI DriverStorage
Need this built for real?

Vinod is a Senior Cloud Architect (22+ yrs) — available for Azure / AWS / GCP architecture, landing zones, and migrations.

Work with me

Comments

Keep Reading