How to Test Spring Boot Applications with Multiple Local Instances
I needed to test how two Spring Boot applications communicate with each other locally. I kept starting one instance, stopping it, changing the port, and starting it again. This was tedious and didn’t let me test actual inter-service communication.
Here’s how I solved this problem and set up multiple local Spring Boot instances for proper integration testing.
The Problem
I was building a microservices architecture where Service A calls Service B. Testing this locally meant I needed both services running simultaneously. My initial approach:
- Start Service A on port 8081
- Stop Service A
- Change config to port 8082
- Start Service B
- Try to remember what Service A was supposed to do
This didn’t work for obvious reasons. I couldn’t test actual HTTP calls between services because only one was running at a time.
Solution: Multiple IntelliJ Run Configurations
The key insight is that you can create multiple run configurations for the same Spring Boot application, each with different configuration parameters.
Step 1: Create a Verification Endpoint
First, I added a simple endpoint to verify which instance is running. This became invaluable for debugging.
@RestController@RequestMapping("/multiple-instance")public class MultipleInstanceController { @Value("${server.port}") private String port;
@Value("${app.instance.name:default}") private String instanceName;
@GetMapping("/ping") public ResponseEntity<String> ping() { return ResponseEntity.ok("Instance is up and running on port " + port); }
@GetMapping("/info") public ResponseEntity<Map<String, String>> info() { return ResponseEntity.ok(Map.of( "port", port, "instance", instanceName, "timestamp", Instant.now().toString() )); }}The @Value annotations inject the port and instance name from configuration. The :default syntax provides a fallback value if app.instance.name isn’t configured.
Step 2: Create Multiple Application Properties
I created separate properties files for each instance.
server.port=8081app.instance.name=instance1spring.application.name=service-aserver.port=8082app.instance.name=instance2spring.application.name=service-bStep 3: Configure IntelliJ Run Configurations
In IntelliJ IDEA, I created separate run configurations:
- Go to Run > Edit Configurations
- Click the + button and select “Spring Boot”
- Name it “Instance1”
- Set Main class to your application class
- In “Active profiles” or “VM options”, add:
-Dspring.profiles.active=instance1
Repeat for Instance2 with -Dspring.profiles.active=instance2.
Alternatively, you can override properties directly in VM options:
-Dserver.port=8081 -Dapp.instance.name=instance1-Dserver.port=8082 -Dapp.instance.name=instance2Step 4: Start Multiple Instances
Now I can start both configurations. IntelliJ lets you run multiple configurations simultaneously by selecting “Run All” or by starting each one individually.
After starting both instances, I verified they were running correctly.
Verifying Instances with curl
I used curl to confirm each instance was responding on its expected port.
curl localhost:8081/multiple-instance/pingOutput:
Instance is up and running on port 8081Then the second instance:
curl localhost:8082/multiple-instance/pingOutput:
Instance is up and running on port 8082The /info endpoint gives more detailed information:
curl localhost:8081/multiple-instance/infoOutput:
{ "port": "8081", "instance": "instance1", "timestamp": "2026-03-26T10:15:30.123Z"}Testing Inter-Instance Communication
With both instances running, I could finally test actual HTTP calls between them. From instance1, I called instance2:
curl -X POST http://localhost:8082/api/process \ -H "Content-Type: application/json" \ -d '{"data": "test from instance1"}'This worked because both instances were running simultaneously. Previously, this would have failed because nothing was listening on port 8082.
Automating Verification
I created a simple bash script to check all instances at once:
#!/bin/bash
for port in 8081 8082 8083 8084; do echo "Checking port $port..." curl -s localhost:$port/multiple-instance/ping || echo " - Not responding"doneOutput:
Checking port 8081...Instance is up and running on port 8081Checking port 8082...Instance is up and running on port 8082Checking port 8083... - Not respondingChecking port 8084... - Not respondingWhy This Approach Works
The verification endpoint pattern serves three purposes:
-
Quick Health Check: The
/pingendpoint confirms the instance is running without complex logic. -
Instance Identification: The
/infoendpoint shows which configuration the instance is using, which helps debug port conflicts or configuration issues. -
Integration Testing: With all instances running, you can test actual HTTP communication between them, simulating a real microservices environment.
Common Issues I Encountered
Port Already in Use: If you forget to stop an instance, starting another on the same port fails. I fixed this by always checking which instances are running first.
Wrong Configuration Applied: Sometimes I thought I was running instance1 but actually had instance2’s configuration. The /info endpoint made it easy to verify which config was active.
Cache Issues: IntelliJ sometimes cached old run configuration settings. I resolved this by invalidating caches (File > Invalidate Caches) when configurations didn’t update properly.
Final Thoughts
Running multiple Spring Boot instances locally transforms how you test microservices. Instead of mocking everything, you can test real HTTP communication, verify load balancing, and catch integration issues early in development.
The verification endpoint pattern is simple but invaluable. It takes five minutes to add and saves hours of debugging time when you’re unsure which instance is responding or whether your configuration is correct.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments