Block & File Storage Best Practices
This is the checklist to run before and after putting an EBS- or EFS-backed workload into production from the SDK.
Busque em todas as páginas da documentação
This is the checklist to run before and after putting an EBS- or EFS-backed workload into production from the SDK.
Each item is a rule stated positively, with a one-line rationale. Work top to bottom - the groups run from encryption and backup, through sizing and networking, to cost and operations. Most rules hold whether you provision from boto3, the AWS SDK v3, or IaC. Remember the recurring theme across this section: the SDK provisions and connects storage, but mounting is always an OS step.
Encrypted: true at create time - encryption cannot be toggled on later without a re-create.KmsKeyId for your own key policy, grants, and rotation; omit it to use the default aws/ebs key.-o tls so NFS traffic is encrypted in transit, not just at rest.Set the encryption flag on creation - it is the one setting you cannot add afterward in place.
# --- Python (boto3) ---
import boto3
ec2 = boto3.client("ec2")
# Encryption must be set at create time; it cannot be turned on later in place.
ec2.create_volume(AvailabilityZone="us-east-1a", Size=50, VolumeType="gp3", Encrypted=True)// --- TypeScript (AWS SDK v3) ---
import { EC2Client, CreateVolumeCommand } from "@aws-sdk/client-ec2";
const ec2 = new EC2Client({});
// Encryption must be set at create time; it cannot be turned on later in place.
await ec2.send(new CreateVolumeCommand({ AvailabilityZone: "us-east-1a", Size: 50, VolumeType: "gp3", Encrypted: true }));CreateSnapshot on a cron.CopySnapshot to a second region gives you a restore path if a region is impaired.ModifyVolume resizes the device only; run growpart then resize2fs/xfs_growfs so the filesystem sees the space.Tune performance on the dials the type supports; do not over-provision size to buy IOPS.
# --- Python (boto3) ---
import boto3
ec2 = boto3.client("ec2")
# gp3 lets IOPS/throughput scale independently of size - no downtime.
ec2.modify_volume(VolumeId="vol-0abc", VolumeType="gp3", Iops=6000, Throughput=250)// --- TypeScript (AWS SDK v3) ---
import { EC2Client, ModifyVolumeCommand } from "@aws-sdk/client-ec2";
const ec2 = new EC2Client({});
// gp3 lets IOPS/throughput scale independently of size - no downtime.
await ec2.send(new ModifyVolumeCommand({ VolumeId: "vol-0abc", VolumeType: "gp3", Iops: 6000, Throughput: 250 }));PosixUser and RootDirectory so each app is jailed to its own subtree with a fixed identity.-o iam ties mounts to instance roles for defense in depth.TransitionToIA/TransitionToArchive - it runs for free.TransitionToPrimaryStorageClass: AFTER_1_ACCESS so re-read files regain full speed.elastic for spiky loads and reserve provisioned for steady, guaranteed throughput you will actually use.volume_available, snapshot_completed) and poll EFS LifeCycleState, since EFS has no waiters.DeleteFileSystem fails while mount targets or access points still exist.VolumeReadOps/burst balance and EFS throughput/IO limits to catch saturation and cost drift early.Wait on state transitions instead of guessing - the SDK gives you the tools for EBS.
# --- Python (boto3) ---
import boto3
ec2 = boto3.client("ec2")
# Block until the volume is ready instead of racing the API.
ec2.get_waiter("volume_available").wait(VolumeIds=["vol-0abc"])// --- TypeScript (AWS SDK v3) ---
import { EC2Client, waitUntilVolumeAvailable } from "@aws-sdk/client-ec2";
const ec2 = new EC2Client({});
// Block until the volume is ready instead of racing the API.
await waitUntilVolumeAvailable({ client: ec2, maxWaitTime: 120 }, { VolumeIds: ["vol-0abc"] });Encrypt everything at rest, and set it at creation. Encryption cannot be turned on in place later - retrofitting it means snapshotting, re-encrypting the snapshot, and re-creating. Enabling EBS encryption-by-default removes the chance of a plaintext volume entirely.
With Amazon Data Lifecycle Manager or AWS Backup, targeting volumes by tag with a retention policy. Snapshots are incremental so frequent ones are cheap, but they outlive the volume - retention rules stop them billing forever.
Call ModifyVolume (no detach), wait until DescribeVolumesModifications reaches optimizing, then grow the filesystem on the instance with growpart and resize2fs/xfs_growfs. Add headroom because you cannot modify the same volume again for about 6 hours.
One per Availability Zone that has clients. Each is a subnet-scoped NFS endpoint; instances mount their in-AZ target to keep traffic local and avoid cross-AZ data charges.
Give each app an access point with its own PosixUser and RootDirectory. That pins a fixed identity and jails the app to its subtree, so tenants cannot see or collide with each other's files.
Only when it is genuinely cold. Lifecycle transitions cut per-GB storage cost sharply but add a per-GB retrieval charge. Pair them with AFTER_1_ACCESS so any file that becomes hot again moves back to primary automatically.
gp3. It is cheaper than gp2 and decouples IOPS and throughput from size. Move to io2 for sustained high-IOPS databases and st1/sc1 for throughput-heavy or cold HDD workloads.
It still has mount targets or access points. Delete all of them first, then DeleteFileSystem succeeds. The same ordering applies in IaC - the dependencies must be torn down first.
Mostly yes. Encryption, tagging, access-point scoping, tight security groups, lifecycle policies, and snapshot retention are architectural habits whether you configure storage from the SDK or from CloudFormation, CDK, or Terraform.
Use waiters where they exist - volume_available and snapshot_completed for EBS - and poll LifeCycleState for EFS, which has no waiters. Acting before a resource is available is a common, avoidable failure.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Revisado por Chris St. John·Última atualização: 23 de jul. de 2026