DEV Community

Guillaume Marchand
Guillaume Marchand

Posted on • Originally published at Medium on

Accelerate Step Functions Development with LocalStack: Testing Workflows Locally While Connecting…

Accelerate Step Functions Development with LocalStack: Testing Workflows Locally While Connecting to Real AWS Services

Developing complex Step Functions workflows often creates a frustrating bottleneck for development teams. Every code change requires a full deployment to AWS, turning what should be a quick iteration into a 30-minute wait. This slow feedback loop hampers productivity and makes debugging workflows unnecessarily difficult.

I want to share how you can accelerate your Step Functions development by using LocalStack to test workflows locally while maintaining connections to real AWS services. This approach reduces your feedback loop from 30 minutes to just few minutes, enabling rapid iteration without sacrificing the reliability of testing against real AWS services.

The Traditional Development Challenge

Step Functions workflows orchestrate multiple AWS services through complex state machines. A typical data ingestion workflow might coordinate multiple different steps using parallel states, map operations, and Lambda integrations with services like Amazon DynamoDB, Amazon Bedrock, and Amazon S3.

Testing these workflows traditionally requires deploying the entire stack to AWS. This creates several problems. Development cycles become slow and expensive. Debugging requires sifting through CloudWatch logs across multiple services. Team members often step on each other when sharing development environments.

The core challenge lies in balancing local development speed with testing authenticity. You want the rapid feedback of local testing, but you also need confidence that your workflow will behave the same way in production when interacting with real AWS services.

Solving the LocalStack Credentials Challenge

LocalStack provides an excellent foundation for local AWS service emulation, but it presents a specific challenge when you want to connect to real AWS services. LocalStack automatically injects fake AWS credentials into Lambda containers, preventing them from accessing actual AWS resources.

When LocalStack starts Lambda containers, it injects environment variables that override your real AWS credentials. Variables like AWS_ACCESS_KEY_ID receive fake values, AWS_ENDPOINT_URL gets redirected to LocalStack's internal endpoints, and AWS_SESSION_TOKEN contains invalid tokens. These injected values prevent your Lambda functions from connecting to real AWS services.

The solution involves understanding how LocalStack manages Lambda execution and configuring it to allow real AWS access. LocalStack runs Lambda containers with a specific user account called sbx_user1051, not the root user. This detail becomes crucial when mounting AWS credentials files.

Implementing the Solution

The implementation requires careful configuration of both LocalStack and your Lambda functions. You configure LocalStack using Docker Compose with specific environment variables that control credential injection and container behavior.

Setting network_mode to host allows LocalStack to mount volumes from the host system. The DISABLE_TRANSPARENT_ENDPOINT_INJECTION flag partially disables LocalStack's automatic endpoint redirection. Most importantly, LAMBDA_DOCKER_FLAGS mounts your AWS credentials file into the correct location within Lambda containers.

The critical insight involves mounting credentials to /home/sbx_user1051/.aws rather than /root/.awsbecause LocalStack's Lambda containers run with the sbx_user1051 user account. This ensures that when your Lambda code calls boto3, it can find and use your real AWS credentials.

Your Lambda functions need modification to handle both local and AWS execution environments. You create a session management module that detects LocalStack execution and removes the injected fake credentials. This allows boto3 to fall back to reading credentials from the mounted file.

The session management code checks for the LOCALSTACK_HOSTNAME environment variable to detect local execution. When running locally, it removes AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, and AWS_ENDPOINT_URL from the environment. This forces boto3 to reload credentials from the mounted AWS credentials file.

Results and Trade-offs

This approach delivers significant productivity improvements. Your development feedback loop accelerates from 10s minutes to some minutes. You test real Lambda code against actual AWS services, ensuring high confidence in your testing.

The solution does involve some trade-offs. You still incur costs for AWS services like Amazon Bedrock and DynamoDB during testing. Temporary credentials require periodic regeneration during development sessions. The LocalStack user account path could potentially change between versions, though this rarely occurs in practice.

Conclusion

LocalStack provides a powerful foundation for accelerating Step Functions development when configured properly to work with real AWS services. By understanding and overcoming the credential injection challenges, you can achieve rapid local iteration while maintaining confidence through testing against production services.

This approach transforms Step Functions development from a slow, deployment-heavy process into a fast, iterative experience. Teams report significant productivity gains and reduced debugging time when implementing this local testing strategy.

The investment in setting up this local development environment pays dividends quickly through faster iteration cycles and more reliable deployments. Your development team can focus on building great workflows rather than waiting for deployments and debugging in production environments.

Top comments (0)