LocalStack LogoLocalStack Icon

Supercharge Your Testing Using JetBrains Aqua with LocalStack

JetBrains Aqua and LocalStack can work together to make testing cloud applications feel much more streamlined. Aqua’s built-in tools for Docker, API testing, and debugging, combined with LocalStack’s fast, local AWS setup, lets you manage everything in one place – no endless switching between terminals. We'll see how to us them to test a real project, from running Terraform and debugging Lambdas to validating RDS data.

Supercharge Your Testing Using JetBrains Aqua with LocalStack

🛠️ Test Smarter, Not Harder

When it comes to developing, testing, and debugging cloud applications, speed and efficiency are non-negotiable. We’ve all been there—waiting forever for AWS resources to spin up, switching between terminals, and piecing together logs from different places. But what if you could manage everything in one place?

That’s where JetBrains Aqua and LocalStack come in — they combine to bring cloud testing closer to home (literally). With Aqua’s all-in-one test automation IDE and LocalStack’s AWS cloud sandbox, you can provision, test, and debug seamlessly without leaving your development environment. It’s not just developers who are benefiting here, this one’s for the QA engineers, and generally anyone who has to deal with testing on a daily basis.

I took these tools for a spin using my previous Dog Management App example — a simple backend powered by:

  • API Gateway
  • Java-based Lambda functions (CRUD for Dog entities 🐶)
  • RDS PostgreSQL database

You can find the full setup and description in the sample repository.

🚀 LocalStack: Because Waiting is Overrated

If you’ve ever deployed to AWS, you know the pain of waiting—provisioning infrastructure feels like watching paint dry. For instance, deploying the Dog Management App’s Terraform config on AWS takes 10+ minutes. With LocalStack? Less than 2 minutes. Over the course of building an app, that can be an eternity of time saved.

Here’s why LocalStack has become my go-to:

  • Blazing-fast iterations – No cloud lag, just instant resource spin-ups.
  • Zero AWS costs – Run your tests without surprise bills.
  • Real AWS behavior, locally – Confidence that your tests will work in production.

For demonstration purposes, this will be the only example I will show you outside the IDE. I think my point is easy to understand: a disproportionate amount of time is spent waiting for resources to spin up in the cloud. Eight minutes might not seem like much, but when you’re iterating on development, it adds up quickly. You’re time is better spent writing code, not waiting for resources to spin up.

🧪 JetBrains Aqua: The Testing Playground

JetBrains Aqua isn’t just another IDE—it’s a one-stop shop for application testing. Aqua integrates seamlessly with Docker, HTTP clients, databases, and even lets me debug AWS Lambda functions like they’re running natively on my machine.

🔥 All-in-One Workflow – No need to switch between tools—code, manage infrastructure, run tests, and debug all in one place.
🐳 Seamless Docker Integration – Easily view and manage LocalStack containers.
🌍 Powerful HTTP Client – Test APIs without context-switching.
📊 Database Support – Run SQL queries and validate persistence effortlessly.
🎯 Built-in Debugging – Step through Java Lambda functions like a local app.

Let’s look at why this matters in action.

🐳 Docker Services in Aqua

When running LocalStack, multiple AWS service containers spin up inside Docker. Aqua’s Services Panel gives me an easy control center for these, allowing me to monitor service health, view real-time logs, and manage containers.

I now prefer using Aqua’s built-in logging instead of jumping into a terminal to run docker logs. It’s faster and keeps me focused:

  • Real-time Logs: Watching Lambda invocations as they happen is super helpful.
  • Search & Filter: Finding specific errors or log entries is a breeze.
  • Multi-Container Logs: Viewing logs from different services side-by-side saves me some time.

Docker containers

At this point everything I need to control is on this interface:

  • Start/Stop/Restart: Managing containers directly from the IDE is convenient.
  • Network Settings: Adjusting container networking helps when debugging LocalStack issues.
  • Exec into Containers: I love being able to exec into any container, run commands, inspect logs, or troubleshoot issues without leaving Aqua. Honestly, Aqua feels like Docker Desktop built right into my IDE. I can run commands, view configurations, check environment variables, inspect exposed ports, and manage containers seamlessly. It’s not as complex, but this is what I use most anyway.

Docker networking

🌐 Testing Endpoints with Aqua’s HTTP Client

One of my favorite features? Aqua’s built-in HTTP Client—because sometimes, you just want to test an API without Postman or a terminal.

🔹 Define API Requests – Easily create requests for endpoints like PUT /dogs and GET /dogs/{id}.
🔹 Add Assertions – Validate responses with JavaScript snippets.
🔹 Run Batch Tests – Group requests into test suites for regression testing.

Here’s a quick test validating a dog update and retrieval:

HTTP Client

As you probably observed, one can define multiple environments, each with its own variables, that the tests can run against. You can also take it one step further and have your preferred IaC tool write the necessary variables to the file when creating the stack. This works great with the API Gateway ID or different ports for your endpoints.

🗃️ SQL Testing with LocalStack’s RDS

Connecting to the PostgreSQL database inside LocalStack is effortless with Aqua. The interface helps me visualize my data, making sure persistence works as expected on the Lambda side:

DB Connection

But SQL queries are not exactly part of my daily routine, so here’s how I like to run some tests:

  • Scenario 1: Just making sure my syntax is correct and works as expected and permissions are in place.

SQL Test

  • Scenario 2: Making sure my data is properly persisted or modified when running a Lambda function.

DB Tables

🐞 Debugging IS Testing: Mastering Lambda Debugging

Let’s face it—debugging is part of testing. I spend a good chunk of my time debugging, and JetBrains IDEs make this process smooth, especially when combined with LocalStack. Disclaimer: I have been using IntelliJ ever since I left university, so I might be biased here, but I’ve tried other IDEs, and these are still my favourite.

Scenario 1: Debugging with -p 5005:5005

In case you haven’t used this configuration before, LocalStack offers a way of passing additional flags to the Lambda containers. Let’s start by setting the Lambda debug flags: LAMBDA_DOCKER_FLAGS="-p 5005:5005" What I like to do is add the _JAVA_OPTIONS environment variable when I create the Lambda function using Terraform. You can, of course, use LAMBDA_DOCKER_FLAGS for this as well. The reason why I prefer this version is that I can always change it using terraform apply

resource "aws_lambda_function" "post_dog" {
function_name = "post-dog"
runtime = "java21"
role = aws_iam_role.lambda_role.arn
handler = "cloud.localstack.postdog.AddDogHandler"
filename = "../api-lambdas/post-dog-lambda/target/post-dog-lambda-1.0.0.jar"
timeout = 300
memory_size = 512
vpc_config {
subnet_ids = [
aws_subnet.private_subnet_1.id,
aws_subnet.private_subnet_2.id,
]
security_group_ids = [aws_security_group.lambda_sg.id]
}
environment {
variables = {
HOST = aws_db_proxy.dogdb_secret_proxy.endpoint
DATABASE_NAME = var.db_name
DB_USER = var.db_username
USER_PASSWORD = var.db_password
_JAVA_OPTIONS = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:5005"
}
}
}

The _JAVA_OPTIONS environment variable is used to pass JVM options when starting a Java application. Make sure you remove this in production. Let’s break down this specific setting:

  • -agentlib:jdwp: This enables the Java Debug Wire Protocol (JDWP), which is used for remote debugging.
  • transport=dt_socket: Specifies that the communication between the debugger and the JVM should happen over a socket.
  • server=y: Tells the JVM to act as a debug server, meaning an external debugger (like JetBrains Aqua) can connect to it.
  • suspend=n: This means the application starts running immediately and does not wait for a debugger to attach. If you set suspend=y, the JVM would pause at startup until a debugger connects.
  • address=0.0.0.0:5005: 0.0.0.0 makes the debug server accessible from any network interface, not just localhost. 5005 is the port on which the JVM will listen for debugger connections.

Pros: It is super easy to attach a debugger like this. Cons: Only one Lambda can run at a time because port 5005 is blocked on the host. Trying to spin up another Lambda causes conflicts. Hence, you won’t see them spin up.

Scenario 2: Debugging with -p 0:5005

We set LAMBDA_DOCKER_FLAGS="-p 0:5005" This assigns a random host port, allowing multiple Lambdas to run simultaneously.

Debugger

Here, I also have two options to choose from:

  • Sub-scenario A: suspend=n The Lambda runs immediately, at least once, before you can debug it. Once the container is up, I can capture the assigned port. Then, I attach the debugger.

  • Sub-scenario B: suspend=y The Lambda starts in a suspended state. Aqua gives me a short window to attach the debugger before the code runs. This is my preferred method when I need to catch issues right from the start.

🏗️ Automated E2E and Integration Testing with Testcontainers

One of the easiest ways to run integration tests is by using Testcontainers. This approach lets me spin up a LocalStack container, provision resources, and run tests against an isolated environment, ensuring my tests are predictable and repeatable. Instead of manually setting up resources, I prefer using the Terraform init hook extension. This allows Terraform configurations to be automatically applied when the container starts. That means I don’t have to programmatically create the services I want to test — I just start the container, and my infrastructure is ready to go. This will also give me the confidence that whatever changes I am making in my IaC files will be reflected in my tests, before pushing code or running them in CI. If something goes wrong, I can always attach a debugger to the LocalStack container, just like with Lambda debugging. Aqua makes it easy to check real-time logs from LocalStack, which helps diagnose failing tests.

Testcontainers

🚀 Final Thoughts

JetBrains Aqua and LocalStack aren’t just tools—they’ve become essential parts of my development workflow. Whether it’s managing infrastructure, testing APIs, querying databases, or debugging Lambda functions, this combo keeps me productive and focused. If you’re tired of juggling between windows and tools, give Aqua and LocalStack a try. For me, having everything in one place has made cloud development feel local, fast, and effortless.


Anca Ghenade
Anca Ghenade
Developer Relations Engineer at LocalStack
With seven years of experience as a developer, Anca transitioned into the developer advocate role. Freshly based in San Francisco, she's always running—both literally and figuratively—to keep pace with and explore the latest in tech.