How to Troubleshoot a Spring Boot Application That Keeps Stopping on an Ubuntu VPS
Keywords: Spring Boot VPS, Ubuntu VPS troubleshooting, Java OOM Killer, Spring Boot memory issue, Nginx 502 Bad Gateway
Introduction
A few days ago, my personal blog suddenly became unstable. The application was running on a small Ubuntu VPS with Spring Boot, PostgreSQL, and Nginx.
Everything looked fine at first. The website worked normally for a while, then suddenly returned a 502 Bad Gateway error. After restarting the service, the website came back online, but the problem kept happening.
If your Spring Boot application randomly stops, crashes, or becomes unreachable on a VPS, this guide will help you troubleshoot the issue step by step.
This article focuses on practical debugging instead of guessing.
Step 1: Check Whether the Application Is Still Running
The first thing to verify is whether your Spring Boot service is actually running.
sudo systemctl status blog
Replace blog with your service name.
If the service is inactive, failed, or restarting repeatedly, you already know the problem is happening at the application level.
Useful commands:
sudo systemctl status blog sudo systemctl restart blog sudo journalctl -u blog -n 100 --no-pager
Step 2: Check the Application Logs
Before changing any configuration, read the logs.
sudo journalctl -u blog -n 200 --no-pager
Look for:
- Java exceptions
- Database connection failures
- Port conflicts
- OutOfMemoryError
- Startup failures
Many developers immediately increase RAM or restart the server without checking logs first. This usually hides the real problem.
Step 3: Verify Nginx
If users see a 502 Bad Gateway page, Nginx is often the messenger, not the cause.
Check whether Nginx is healthy:
sudo systemctl status nginx
Check recent logs:
sudo journalctl -u nginx -n 100 --no-pager
Common scenarios:
- Spring Boot is down
- Spring Boot is listening on the wrong port
- Reverse proxy configuration is incorrect
If Nginx is healthy but the backend is unavailable, continue with the next steps.
Step 4: Check Memory Usage
Memory problems are one of the most common reasons for unexpected application crashes.
free -h
Example:
Mem: 1.9Gi total Used: 1.1Gi Available: 569Mi Swap: 0B
Pay special attention to:
- Available memory
- Swap size
A server with no swap is much more vulnerable to memory spikes.
Step 5: Check for OOM Killer Events
Linux includes a protection mechanism called the Out Of Memory (OOM) Killer.
When the operating system runs out of memory, it may terminate processes automatically.
Check kernel logs:
journalctl -k | grep -i oom
Or:
dmesg -T | grep -i "killed process"
If you see messages similar to:
Out of memory: Killed process 12345 (java)
you have found the real cause.
In my case, Linux repeatedly killed the Java process even though the application was configured with memory limits.
For a detailed explanation of this issue, see:
→ How I Fixed a Spring Boot Application That Kept Getting Killed by the Linux OOM Killer
Step 6: Identify the Largest Memory Consumers
Check which processes consume the most memory.
ps aux --sort=-rss | head -20
Typical services include:
- Java
- PostgreSQL
- Redis
- Docker
- Elasticsearch
- Nginx
Do not assume Spring Boot is always the problem.
In my investigation, I discovered that Docker services were still running even though I was not actively using containers.
Step 7: Verify Your Java Memory Settings
Review your systemd service configuration.
systemctl cat blog
Example:
ExecStart=/usr/bin/java \ -Xms256m \ -Xmx512m \ -XX:+UseG1GC \ -jar app.jar
For small VPS servers, setting a maximum heap size is important.
Without limits, Java may consume more memory than expected.
For more details, see:
→ My Spring Boot Memory Settings for a Small 2GB VPS
Step 8: Check Whether Swap Exists
Many developers skip this step.
Check swap:
swapon --show
Or:
free -h
If you see:
Swap: 0B
consider creating a swap file.
A lack of swap was the main reason my server became unstable.
Step 9: Create Swap Space
For a VPS with 2GB RAM:
sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile
Persist after reboot:
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Verify:
free -h
You should now see swap space available.
For a deeper discussion about swap, see:
→ Why a 2GB VPS Needs Swap Space for Spring Boot Applications
Step 10: Check PostgreSQL Memory Usage
PostgreSQL is usually efficient, but it is still worth checking.
Useful settings:
show shared_buffers; show work_mem; show effective_cache_size;
For small servers, avoid allocating excessive memory to PostgreSQL.
Remember that PostgreSQL, Java, Nginx, and the operating system all compete for the same RAM.
Step 11: Review System Logs and Journal Usage
System logs are useful, but they should not grow forever.
Check journal size:
journalctl --disk-usage
Limit journal retention if necessary:
SystemMaxUse=200M RuntimeMaxUse=100M
This helps keep small VPS instances clean and predictable.
→ What Is systemd-journald and Should You Limit Its Log Size?
Step 12: Monitor Before Making More Changes
After applying fixes, continue monitoring.
Useful commands:
free -h
ps aux --sort=-rss | head -20
journalctl -k | grep -i oom
Avoid making multiple changes at the same time.
Change one thing, observe the result, then continue.
Final Checklist
When a Spring Boot application keeps stopping on Ubuntu:
- Verify the service status.
- Read the application logs.
- Check Nginx.
- Check memory usage.
- Search for OOM Killer events.
- Identify memory-heavy processes.
- Review Java memory settings.
- Verify swap configuration.
- Check PostgreSQL memory settings.
- Monitor the server after applying fixes.
In my case, the root cause was surprisingly simple: a 2GB VPS running without swap. Once swap was added, the application became stable again.
The lesson is simple: always investigate first and optimize second.
Production issues are often caused by infrastructure details that are easy to overlook.