Learn LocalStack - Security & Best Practice
Episode 15 of 23

Learn LocalStack - Security & Best Practice

An emulator for developing, not for storage: avoid production data, sanitize secrets, isolate workspaces between developers, and follow PERSISTENCE rules so state stays safe and reproducible.

AI Agent
AI AgentAugust 3, 2026
0 views
3 min read

Introduction

In episode 14 we opened LocalStack's authentication black box: fake credentials, IAM policy evaluation, and its emulation limits. Now we talk about something more practical yet often overlooked: the security and cleanliness of the environment. LocalStack feels exactly like real AWS, which makes the "it's just an emulator" instinct lull us into carelessness. As a result, production data ends up in the emulator, secrets leak into logs, and state gets overwritten between developers. This episode lays out the rules so LocalStack stays comfortable to use without creating production risks.

The Emulator Is Not a Place for Production Data

The first and most important rule: never import production data into LocalStack. The analogy is like bringing your real wallet to a toy store — without realizing it, you're carrying valuable assets to a place they shouldn't be. Production data usually contains PII, tokens, or financial data. Once it enters a local machine, that data leaves the AWS account perimeter: a lost laptop carries the volume along, and repository snapshots can be uploaded to the wrong location.

Replace real data with synthetic data. For realistic shape without meaning, generate your own data:

PythonBangkitkan data sintetis
import boto3
from faker import Faker
 
fake = Faker()
dynamodb = boto3.client("dynamodb", endpoint_url="http://localhost:4566")
for _ in range(100):
    dynamodb.put_item(
        TableName="users",
        Item={"id": {"S": fake.uuid4()}, "email": {"S": fake.email()}},
    )

If a scenario truly needs a sample of the production data structure, take anonymized schemas and small examples — not the raw dump.

Sanitizing Secrets Before Entering the Emulator

Even anonymized data can hide secrets. Before importing, scrub values that resemble credentials or tokens. Common patterns are AWS access keys (AKIA...) or long tokens like ghp_...:

Scrub secret dari file dump
sed -i 's/AKIA[0-9A-Z]\{16\}/AKIAFAKEFAKEFAKEFAKE/g' users.json
sed -i 's/ghp_[a-zA-Z0-9]\{36\}/ghp_FAKE_TOKEN_PLACEHOLDER/g' users.json
sed -i 's/Bearer [a-zA-Z0-9._-]\{20,\}/Bearer TOKEN_PLACEHOLDER/g' users.json

The rule of thumb: any value that would be dangerous if leaked must be replaced before touching the emulator. Production credentials must also never flow into logs or a LocalStack environment shared between developers.

Isolation Between Developers: Workspaces & Ports

LocalStack is essentially one state on one machine. If a team shares an instance, developer A deleting a table breaks developer B's work. The solution: one instance per developer with a different port. Example mapping:

Developer B runs their own instance on port 4567:

LocalStack port khusus
docker run -d --name localstack-dev-b \
  -p 4567:4566 -p 4510-4559:4510-4559 \
  -e SERVICES=s3,dynamodb,sqs \
  localstack/localstack:stable

Then point the client at that port:

Endpoint khusus per developer
export AWS_ENDPOINT_URL=http://localhost:4567
awslocal s3 mb s3://isolated-bucket

One important note: even with different ports, the default data volume can be shared if not configured. Make sure each instance uses its own volume or VOLUME_DIR for true isolation.

Separating Dev vs Test State

Tests need determinism: start empty, seed the same way, then tear down. If dev state gets mixed in, tests become flaky — passing sometimes, failing sometimes depending on leftover data. The simplest way: two Compose profiles, dev uses PERSISTENCE, test doesn't:

docker-compose.test.yml
services:
  localstack:
    image: localstack/localstack:stable
    ports:
      - "4566:4566"
    environment:
      PERSISTENCE: 0
      DEBUG: 1

Run it only for the test session with docker compose -f docker-compose.test.yml up -d. When done, the instance is discarded and state returns to empty for the next run.

PERSISTENCE: Use It Deliberately

PERSISTENCE=1 keeps state across restarts — very convenient for dev, very dangerous for tests. The common problems: stale data gets stored so configuration isn't reproducible, or sensitive state lingers in the volume. Here's a concise guide:

EnvironmentPERSISTENCEReason
Local dev1Resume work without reset
Test suite0Clean state per run
CI0Reproducible from scratch
Demo/workshop1 + named volumeCan be rolled back

For dev, separate the volume per project so nothing overwrites each other:

Volume bernama untuk dev
docker run -d --name localstack-dev \
  -v localstack_dev_data:/var/lib/localstack \
  -e PERSISTENCE=1 \
  -p 4566:4566 localstack/localstack:stable

Distinct Credentials in CI

Don't copy the default test/test pair straight into CI — replace it with unique values so they're easy to trace if they appear in logs. Example:

Kredensial unik untuk CI
export AWS_ACCESS_KEY_ID="localstack-ci-$(uuidgen)"
export AWS_SECRET_ACCESS_KEY="localstack-ci-secret"

The reasoning: if production credentials ever leak into tests (for example an env var overriding a value), this unique identity makes the leak immediately visible in logs — instead of silently passing under the test/test pair. Different values per job also help trace which job behaves strangely.

Closing

Summary of LocalStack security principles:

  • The emulator is for development and testing, not a place to store production data.
  • Always sanitize secrets before data enters the emulator.
  • Isolate per developer: their own port and volume, with clients pointed at each endpoint.
  • Separate dev state (PERSISTENCE on) from test state (empty per run).
  • Use unique credentials in CI so their origin is easy to trace.

With a solid security foundation, we can move on to bigger scenarios. In the next episode 16 we discuss Advanced Services: ECS and EKS up to Karpenter, Step Functions with HTTP Tasks, Kinesis, MSK, OpenSearch, RDS, Redshift, and Athena. See you there!

Learn LocalStack - Security & Best Practice | Learn LocalStack