Skip to main content

S3

Protocol: REST XML
Endpoint: http://localhost:4566/{bucket}/{key}
S3 supports versioning, multipart upload, pre-signed URLs, Object Lock (COMPLIANCE/GOVERNANCE modes), event notifications, and 50+ operations.
CategoryOperations
BucketsListBuckets, CreateBucket, HeadBucket, DeleteBucket, GetBucketLocation
ObjectsPutObject, GetObject, GetObjectAttributes, HeadObject, DeleteObject, DeleteObjects, CopyObject
ListingListObjects, ListObjectsV2, ListObjectVersions
MultipartCreateMultipartUpload, UploadPart, CompleteMultipartUpload, AbortMultipartUpload, ListMultipartUploads
VersioningPutBucketVersioning, GetBucketVersioning
TaggingPutBucketTagging, GetBucketTagging, PutObjectTagging, GetObjectTagging, DeleteObjectTagging
PolicyPutBucketPolicy, GetBucketPolicy, DeleteBucketPolicy
CORSPutBucketCors, GetBucketCors, DeleteBucketCors
LifecyclePutBucketLifecycle, GetBucketLifecycle, DeleteBucketLifecycle
ACLPutBucketAcl, GetBucketAcl, PutObjectAcl, GetObjectAcl
EncryptionPutBucketEncryption, GetBucketEncryption, DeleteBucketEncryption
NotificationsPutBucketNotification, GetBucketNotification
Object LockPutObjectLockConfiguration, GetObjectLockConfiguration, PutObjectRetention, GetObjectRetention, PutObjectLegalHold, GetObjectLegalHold
Pre-signed URLsGenerates and validates pre-signed GET/PUT URLs
S3 SelectSelectObjectContent

Configuration

floci:
  services:
    s3:
      enabled: true
      default-presign-expiry-seconds: 3600
  auth:
    presign-secret: local-emulator-secret

Path-Style URLs

Floci uses path-style URLs:
http://localhost:4566/my-bucket/my-key
When using the AWS SDK, enable path-style mode:
S3Client s3 = S3Client.builder()
    .endpointOverride(URI.create("http://localhost:4566"))
    .serviceConfiguration(S3Configuration.builder()
        .pathStyleAccessEnabled(true)
        .build())
    .build();

Examples

export AWS_ENDPOINT=http://localhost:4566

# Create bucket
aws s3 mb s3://my-bucket --endpoint-url $AWS_ENDPOINT

# Upload a file
aws s3 cp ./report.pdf s3://my-bucket/reports/report.pdf --endpoint-url $AWS_ENDPOINT

# Upload inline content
echo '{"hello":"world"}' | aws s3 cp - s3://my-bucket/data.json --endpoint-url $AWS_ENDPOINT

# Download
aws s3 cp s3://my-bucket/data.json ./data.json --endpoint-url $AWS_ENDPOINT

# Inspect object attributes without downloading the body
aws s3api get-object-attributes \
  --bucket my-bucket \
  --key data.json \
  --object-attributes ETag ObjectSize StorageClass \
  --endpoint-url $AWS_ENDPOINT

# List
aws s3 ls s3://my-bucket --endpoint-url $AWS_ENDPOINT

# Delete
aws s3 rm s3://my-bucket/data.json --endpoint-url $AWS_ENDPOINT

# Enable versioning
aws s3api put-bucket-versioning \
  --bucket my-bucket \
  --versioning-configuration Status=Enabled \
  --endpoint-url $AWS_ENDPOINT

# Generate a pre-signed URL (valid for 1 hour)
aws s3 presign s3://my-bucket/report.pdf \
  --expires-in 3600 \
  --endpoint-url $AWS_ENDPOINT

DynamoDB

Protocol: JSON 1.1 (X-Amz-Target: DynamoDB_20120810.*)
Endpoint: POST http://localhost:4566/
DynamoDB supports Global Secondary Indexes (GSI), Local Secondary Indexes (LSI), Query and Scan operations, TTL, ACID transactions, and batch operations.
ActionDescription
CreateTableCreate a table with indexes
DeleteTableDelete a table
DescribeTableGet table metadata
ListTablesList all tables
UpdateTableUpdate throughput, indexes, streams
PutItemWrite an item
GetItemRead an item by primary key
DeleteItemDelete an item
UpdateItemPartially update an item
QueryQuery by partition key with optional filter
ScanFull table scan with optional filter
BatchWriteItemWrite/delete up to 25 items across tables
BatchGetItemRead up to 100 items across tables
TransactWriteItemsACID write transaction
TransactGetItemsACID read transaction
DescribeTimeToLiveGet TTL configuration
UpdateTimeToLiveEnable/disable TTL on a table
TagResourceTag a table
UntagResourceRemove tags
ListTagsOfResourceList tags on a table

Examples

export AWS_ENDPOINT=http://localhost:4566

# Create a table
aws dynamodb create-table \
  --table-name Users \
  --attribute-definitions \
    AttributeName=userId,AttributeType=S \
  --key-schema \
    AttributeName=userId,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST \
  --endpoint-url $AWS_ENDPOINT

# Put an item
aws dynamodb put-item \
  --table-name Users \
  --item '{"userId":{"S":"u1"},"name":{"S":"Alice"},"age":{"N":"30"}}' \
  --endpoint-url $AWS_ENDPOINT

# Get an item
aws dynamodb get-item \
  --table-name Users \
  --key '{"userId":{"S":"u1"}}' \
  --endpoint-url $AWS_ENDPOINT

# Query (partition key)
aws dynamodb query \
  --table-name Users \
  --key-condition-expression "userId = :id" \
  --expression-attribute-values '{":id":{"S":"u1"}}' \
  --endpoint-url $AWS_ENDPOINT

# Scan with filter
aws dynamodb scan \
  --table-name Users \
  --filter-expression "age > :min" \
  --expression-attribute-values '{":min":{"N":"25"}}' \
  --endpoint-url $AWS_ENDPOINT

# Enable TTL
aws dynamodb update-time-to-live \
  --table-name Users \
  --time-to-live-specification Enabled=true,AttributeName=expiresAt \
  --endpoint-url $AWS_ENDPOINT

# Create a table with a Global Secondary Index
aws dynamodb create-table \
  --table-name Orders \
  --attribute-definitions \
    AttributeName=orderId,AttributeType=S \
    AttributeName=customerId,AttributeType=S \
  --key-schema AttributeName=orderId,KeyType=HASH \
  --global-secondary-indexes '[{
    "IndexName": "CustomerIndex",
    "KeySchema": [{"AttributeName":"customerId","KeyType":"HASH"}],
    "Projection": {"ProjectionType":"ALL"}
  }]' \
  --billing-mode PAY_PER_REQUEST \
  --endpoint-url $AWS_ENDPOINT

DynamoDB Streams

Protocol: JSON 1.1 (X-Amz-Target: DynamoDBStreams_20120810.*)
Endpoint: POST http://localhost:4566/
DynamoDB Streams capture item-level changes in a table and expose them via shard iterators. They also serve as the event source for Lambda ESM triggers.
ActionDescription
ListStreamsList all streams
DescribeStreamGet stream and shard info
GetShardIteratorGet a shard iterator
GetRecordsRead stream records from a shard

Example

export AWS_ENDPOINT=http://localhost:4566

# Enable Streams on a table
aws dynamodb update-table \
  --table-name Users \
  --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
  --endpoint-url $AWS_ENDPOINT

# Connect a Lambda function to the stream
STREAM_ARN=$(aws dynamodb describe-table \
  --table-name Users \
  --query 'Table.LatestStreamArn' --output text \
  --endpoint-url $AWS_ENDPOINT)

aws lambda create-event-source-mapping \
  --function-name my-function \
  --event-source-arn $STREAM_ARN \
  --starting-position LATEST \
  --endpoint-url $AWS_ENDPOINT

Secrets Manager

Protocol: JSON 1.1 (X-Amz-Target: secretsmanager.*)
Endpoint: POST http://localhost:4566/
Secrets Manager supports versioned secrets, resource policies, and tagging.
ActionDescription
CreateSecretCreate a new secret
GetSecretValueRetrieve the current secret value
PutSecretValueUpdate the secret value (new version)
UpdateSecretUpdate secret metadata or value
DescribeSecretGet secret metadata and version info
ListSecretsList all secrets
DeleteSecretDelete a secret (with recovery window)
RotateSecretTrigger secret rotation via a Lambda
ListSecretVersionIdsList all versions of a secret
GetResourcePolicyGet the resource policy
PutResourcePolicyAttach a resource policy
DeleteResourcePolicyRemove the resource policy
TagResourceTag a secret
UntagResourceRemove tags

Configuration

floci:
  services:
    secretsmanager:
      enabled: true
      default-recovery-window-days: 30   # Days before a deleted secret is purged

Examples

export AWS_ENDPOINT=http://localhost:4566

# Create a string secret
aws secretsmanager create-secret \
  --name /app/database-url \
  --secret-string "postgresql://admin:secret@localhost/mydb" \
  --endpoint-url $AWS_ENDPOINT

# Create a JSON secret
aws secretsmanager create-secret \
  --name /app/api-keys \
  --secret-string '{"stripe":"sk_test_xxx","sendgrid":"SG.xxx"}' \
  --endpoint-url $AWS_ENDPOINT

# Retrieve a secret
aws secretsmanager get-secret-value \
  --secret-id /app/database-url \
  --endpoint-url $AWS_ENDPOINT

# Update a secret
aws secretsmanager put-secret-value \
  --secret-id /app/database-url \
  --secret-string "postgresql://admin:new-password@localhost/mydb" \
  --endpoint-url $AWS_ENDPOINT

# List secrets
aws secretsmanager list-secrets --endpoint-url $AWS_ENDPOINT

# Delete with recovery window
aws secretsmanager delete-secret \
  --secret-id /app/database-url \
  --recovery-window-in-days 7 \
  --endpoint-url $AWS_ENDPOINT

# Delete immediately (no recovery)
aws secretsmanager delete-secret \
  --secret-id /app/database-url \
  --force-delete-without-recovery \
  --endpoint-url $AWS_ENDPOINT

SSM Parameter Store

Protocol: JSON 1.1 (X-Amz-Target: AmazonSSM.*)
Endpoint: POST http://localhost:4566/
SSM Parameter Store supports version history, labels, SecureString parameters, and tagging. All AWS parameter types are accepted: String, StringList, and SecureString.
SecureString parameters are stored as-is without actual KMS encryption in Floci. The type is preserved and returned correctly, but the value is not encrypted at rest.
ActionDescription
PutParameterCreate or update a parameter
GetParameterGet a single parameter by name
GetParametersGet multiple parameters by name
GetParametersByPathGet all parameters under a path prefix
DeleteParameterDelete a parameter
DeleteParametersDelete multiple parameters
GetParameterHistoryList all versions of a parameter
DescribeParametersList parameters with optional filters
LabelParameterVersionAttach a label to a specific version
AddTagsToResourceTag a parameter
ListTagsForResourceList tags on a parameter
RemoveTagsFromResourceRemove tags from a parameter

Configuration

floci:
  services:
    ssm:
      enabled: true
      max-parameter-history: 5   # Versions retained per parameter
  storage:
    services:
      ssm:
        mode: memory
        flush-interval-ms: 5000

Examples

export AWS_ENDPOINT=http://localhost:4566

# Store parameters
aws ssm put-parameter --endpoint-url $AWS_ENDPOINT \
  --name /app/db/host --value "localhost" --type String

aws ssm put-parameter --endpoint-url $AWS_ENDPOINT \
  --name /app/db/password --value "secret" --type SecureString

# Retrieve
aws ssm get-parameter --endpoint-url $AWS_ENDPOINT \
  --name /app/db/host

aws ssm get-parameters-by-path --endpoint-url $AWS_ENDPOINT \
  --path /app/ --recursive

# Delete
aws ssm delete-parameter --endpoint-url $AWS_ENDPOINT \
  --name /app/db/host

Build docs developers (and LLMs) love