Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
FREEDOM251

Freedom251 › Blog › Apache Tomcat

How to Optimize Your Tomcat Installation on Ubuntu (2026 Guide)

By Freedom251 Team · · 12 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The safest way to optimize Tomcat on Ubuntu is to measure the bottleneck first, then change one class of settings at a time. Track throughput, p95 and p99 latency, errors, CPU, heap occupancy, garbage-collection pauses, active and queued requests, connections, and database or API saturation before and after every change.

Ubuntu’s packaged tomcat10, a tarball installation, and a containerized deployment use different paths and service controls. Confirm which installation you have, size the JVM for the measured live set rather than a fixed percentage of RAM, and tune connector concurrency only when the workload and downstream systems can support it.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Start with a measurable baseline

Optimization is a comparison exercise, not a hunt for a magic server.xml value. Record a representative traffic window under normal load and, if relevant, a controlled peak test. Keep the request mix, application version, Java version, hardware, proxy settings, and database state constant while testing.

Metric What to record What it tells you
Request rate Requests per second, separated by important endpoints Whether a change increases useful work rather than merely queueing more requests
Latency p50, p95, and p99, plus the slowest important transactions Whether tail latency improves; averages can hide queueing and pauses
Errors HTTP 4xx/5xx, timeouts, rejected connections, and application exceptions Whether higher throughput is being purchased with failures
CPU Tomcat process and host utilization, ideally by core Whether the bottleneck is computation, contention, or waiting
Heap and GC Used heap after warm-up, high-water mark, collection frequency, and pause duration Whether the JVM has headroom or is spending time reclaiming memory
Concurrency Busy request threads, queued requests, and executor utilization Whether requests are blocked on I/O or simply competing for CPU
Connections Open, keep-alive, and rejected connections Whether the connector, proxy, or operating-system backlog is limiting intake
Downstream services Database pool usage, query latency, API latency, and saturation signals Whether Tomcat tuning would only move the bottleneck into another tier

Keep a change log with the exact setting, timestamp, traffic window, Java and Tomcat versions, and rollback result. A configuration that raises requests per second but worsens p99 latency or database saturation is not an improvement for most production services.

Identify the Ubuntu installation and service layout

On Ubuntu Noble, the packaged tomcat10 service includes the unit file /usr/lib/systemd/system/tomcat10.service, policy and configuration files under /etc/tomcat10, and runtime configuration, logs, and work directories under /var/lib/tomcat10/conf, /var/lib/tomcat10/logs, and /var/lib/tomcat10/work. A tarball installation under a path such as /opt/tomcat has a different layout and may not use the Ubuntu unit at all.

Confirm the actual deployment before editing anything:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo systemctl status tomcat10
sudo systemctl cat tomcat10
sudo journalctl -u tomcat10 -b
systemctl show tomcat10 -p FragmentPath -p DropInPaths -p Environment

The unit output identifies the executable, any EnvironmentFile, drop-ins, user, working directory, and configuration arguments. Edit the files named by that unit rather than assuming a path from another installation. Keep the service account separate from root; Apache’s Tomcat 10.1 setup guidance states: “For optimal security, the service should be run as a separate user, with reduced permissions.”

Use a safe, reversible tuning workflow

  1. Capture the baseline. Save the metrics listed above and note the exact package, Java, and Tomcat versions.
  2. Back up configuration. Copy the environment file identified by the unit, the active XML configuration tree, and any systemd drop-ins to a dated directory owned by an administrator.
  3. Change one class of settings. For example, change JVM memory first, then test; do not simultaneously alter heap, thread pools, compression, and CPU affinity.
  4. Validate syntax and startup. Run sudo systemctl daemon-reload after a drop-in change, restart Tomcat, and inspect systemctl status and journalctl -u tomcat10 -b immediately.
  5. Run a smoke test. Exercise health checks, authentication, representative read and write requests, uploads, scheduled jobs, and any TLS or HTTP/2 path that production uses.
  6. Compare the same metrics. Keep the change only if the target metric improves without unacceptable errors, tail latency, resource use, or downstream saturation.
  7. Roll back quickly. Restore the saved environment or XML files, reload systemd when necessary, restart, and confirm that the previous measurements return.

Set JVM memory in CATALINA_OPTS

Why the variable matters

Tomcat starts several Java processes and commands. JAVA_OPTS is applied broadly, including commands used to stop or inspect Tomcat, while CATALINA_OPTS is intended for the JVM that runs the server. Apache’s current RUNNING.txt says: “Do not use JAVA_OPTS to specify memory limits. You do not need much memory for a small process that is used to stop Tomcat. Those settings belong to CATALINA_OPTS.” Put -Xms and -Xmx in the package-supported CATALINA_OPTS mechanism.

Find the supported package mechanism

Read the unit and its referenced environment file first. If the package uses an environment file, edit the existing CATALINA_OPTS value there and preserve flags already supplied by Ubuntu. If you need an isolated override, use a systemd drop-in:

sudo systemctl edit tomcat10

Add a [Service] section and an Environment assignment containing your complete, merged CATALINA_OPTS value. The following is only a syntax example; the heap numbers are not universal recommendations:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
[Service]
Environment='CATALINA_OPTS=-Xms1g -Xmx2g'

After saving, run:

sudo systemctl daemon-reload
sudo systemctl restart tomcat10
systemctl show tomcat10 -p Environment
ps -o pid,args -C java

If a drop-in replaces an existing assignment, include the existing operational flags in the new value. Verify the running command line rather than assuming that a file edit was consumed.

Choose -Xms and -Xmx from observations

Size the heap from the application’s observed live set, garbage-collection behavior, and the memory limit of the VM, container, or systemd scope. Leave headroom for metaspace, thread stacks, direct and other native buffers, loaded libraries, the page cache, and the operating system. A host with 8 GB of RAM does not have 8 GB available for -Xmx.

  1. Warm the application with normal traffic and capture used-heap and post-GC occupancy.
  2. Observe a complete business cycle, including scheduled jobs, large reports, uploads, caches, and traffic spikes.
  3. Set -Xmx above the measured live set by a margin that prevents constant collection, while keeping total process and host memory within the actual limit.
  4. Set -Xms according to startup behavior and available memory. A large initial heap can reduce resizing but can also starve other services.
  5. Restart and verify heap flags with the Java command line or, when a JDK is installed, tools such as jcmd <pid> VM.flags and jcmd <pid> GC.heap_info.

More heap is not a substitute for fixing a leak or an oversized cache. If occupancy rises continuously after collections, investigate retained objects and application behavior. If the kernel kills Java while the heap appears below -Xmx, check native memory, thread count, container limits, and the system journal.

Tune the HTTP connector and executor by queue behavior

Understand the thread-pool controls

maxThreads limits simultaneous request-processing threads when the connector owns its pool. An associated Tomcat Executor takes precedence over connector-level thread-pool attributes, so changing maxThreads on a connector may have no effect when that connector references an executor.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Setting or example Documented value How to use it
maxThreads Default 200 in the cited Tomcat 8.5/10-era connector reference Verify the exact installed version; increase only when requests wait on I/O and downstream systems can absorb more concurrent work
minSpareThreads Default 10 Controls ready capacity; raising it consumes memory and threads without helping a CPU-bound service
NIO pollerThreadCount One per processor, capped at two, by default Leave the documented default unless profiling shows a connector event-loop problem
Sample connector Port 8080, connectionTimeout 20000 ms, redirectPort 8443 These are sample configuration values, not workload targets
Sample shared executor maxThreads 150 and minSpareThreads 4 Use as an example of wiring, not as a recommended production pool size

Decide whether more threads will help

  • If CPU is already saturated, adding threads usually increases context switching and contention. Reduce work or scale out instead of raising concurrency.
  • If threads are mostly blocked on database or remote API I/O, a larger pool can improve throughput, but only until the downstream pool, rate limit, or service becomes saturated.
  • If active threads are low while latency is high, inspect the database, remote calls, locks, disk, and garbage collection before changing Tomcat.
  • If the queue grows while CPU is available, confirm that the executor is the pool actually in use and that the application is not blocking on a smaller internal pool.

Use acceptCount, timeouts, and keep-alive deliberately

acceptCount controls the queue for connections that arrive while request threads are busy. Raise it only when short bursts create a measurable queue and the operating-system listen backlog, reverse proxy, and file-descriptor limits are configured to support it. A larger queue can turn an immediate refusal into a long timeout, worsening p99 latency.

Align connectionTimeout and keep-alive behavior with the reverse proxy or load balancer. If the proxy closes an idle connection earlier than Tomcat, clients see avoidable resets; if Tomcat holds thousands of idle connections longer than the proxy, memory and file descriptors are wasted. Test with the same proxy path used by clients, not only with a direct connection to port 8080.

The connector reference documents tcpNoDelay as true by default and notes that it generally improves performance. Do not disable it without a measured reason.

Compression is a CPU-versus-bandwidth trade-off

Compression can reduce bandwidth for text responses, especially across a constrained network, but it consumes CPU and can increase latency for small or already-compressed payloads. Measure response sizes, CPU, and p95/p99 latency before enabling it broadly. Limit compression to suitable text content and exclude formats that are already compressed when your connector and proxy policy allow that distinction.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Example connector wiring

A connector and shared executor must be placed in the active server.xml selected by the service. Escape XML correctly and validate the file after editing:

<Executor name='tomcatThreadPool' maxThreads='150' minSpareThreads='4'/>
<Connector executor='tomcatThreadPool' port='8080' connectionTimeout='20000' redirectPort='8443'/>

The values above reproduce Apache’s sample configuration. They are not a sizing prescription. Change one attribute, restart, and compare the baseline metrics.

Keep XML and features version-aware

Tomcat 10.1.60’s configuration reference describes a schemaless, case-sensitive XML configuration and property substitution from JVM and other supported property sources. An attribute copied from another Tomcat major release may be ignored, rejected, or behave differently. Check the installed version before adding connector, executor, TLS, HTTP/2, or protocol attributes.

For a package installation, useful checks include:

dpkg-query -W tomcat10
sudo systemctl cat tomcat10
sudo -u tomcat catalina.sh version

Use the command that matches the service account and installation path; a tarball may expose catalina.sh somewhere else. Keep a known-good XML copy so a failed parse can be reversed without reconstructing the file.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

TLS, HTTP/2, and management exposure

The sample server.xml includes optional TLS and HTTP/2 connectors. Terminate TLS at a trusted reverse proxy when that matches your architecture, or configure Tomcat’s TLS connector with current certificates, protocol settings, and a tested renewal process. Do not expose the shutdown port, manager application, host-manager application, or administrative endpoints to untrusted networks. Performance tuning does not justify weakening those boundaries.

Apply security updates before judging performance

Ubuntu security notice USN-8417-1, published 10 June 2026, lists multiple Tomcat issues, including request-body memory exhaustion and HTTP/2 handling problems, and provides fixed package versions. Update the Ubuntu package and restart Tomcat before comparing resource use:

sudo apt update
apt-cache policy tomcat10
sudo apt install --only-upgrade tomcat10
sudo systemctl restart tomcat10

Record the installed Tomcat and Java versions, run the smoke tests, and compare the same latency, error, heap, and connection metrics. A security update can change resource use or request handling; treat it as a new baseline rather than attributing every difference to a tuning change.

Consider systemd CPU and NUMA placement only after profiling

Ubuntu documents persistent systemd controls including CPUAffinity=, NUMAPolicy=, and NUMAMask=. They can help specialized, latency-sensitive deployments, but they constrain where Tomcat may run. A narrower CPU set can reduce total capacity, and an unsuitable NUMA mask can increase remote-memory access.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Profile per-core CPU utilization, run-queue pressure, context switching, and memory locality during representative load.
  2. Apply one placement control in a systemd drop-in, keeping the previous drop-in as a rollback copy.
  3. Restart and compare p95/p99 latency, throughput, CPU utilization, GC pauses, and downstream timings.
  4. Remove the restriction if capacity falls or tail latency moves to another tier.

Do not use CPU affinity to conceal an application or database bottleneck. Placement is a final refinement after JVM, connector, and downstream behavior are understood.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Compare candidate configurations consistently

Use a small experiment matrix rather than changing settings opportunistically. For each candidate, run the same workload long enough to include warm-up and normal cache behavior:

Comparison dimension Acceptance question
p95 and p99 latency Did tail latency improve for the endpoints users care about?
Throughput at a fixed error rate Can the service process more requests without increasing failures?
CPU utilization Is extra capacity real, or is the host now contending?
Heap and GC pauses Did memory headroom improve without longer pauses?
Active and queued requests Did queueing fall, and is the selected executor actually controlling it?
Connection count and rejects Are proxy, connector, backlog, and file-descriptor limits aligned?
Database and API saturation Did Tomcat simply transfer the bottleneck downstream?

Keep the configuration that improves the target metric without violating error, latency, memory, or downstream limits. There is no universal percentage speed-up for Tomcat on Ubuntu; the result depends on traffic, Java version, hardware, application code, and dependencies.

Troubleshoot common tuning failures

Tomcat fails immediately after an edit

Read the current boot journal first. XML is case-sensitive and schemaless, so a misspelled or unsupported attribute can prevent startup. Restore the last known-good XML, verify the installed Tomcat version, and reintroduce the change only after confirming that the attribute belongs to that version.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The new heap values do not appear

Check systemctl cat tomcat10 for the active environment file and drop-ins, then inspect systemctl show tomcat10 -p Environment and the running Java command line. A connector or service may be using a different installation, or a later environment assignment may override the value. Ensure the flags are in CATALINA_OPTS, not only in a shell profile unavailable to systemd.

Memory exhaustion continues after raising -Xmx

Distinguish a Java heap exception from a kernel or container out-of-memory kill. Check the service journal, host memory, cgroup limits, native allocations, thread count, direct buffers, metaspace, and retained application objects. Raising the heap can make a kernel kill more likely if total process memory exceeds the real limit.

Latency worsens after increasing maxThreads

Check CPU, run queues, GC pauses, database pool wait time, and remote API latency. More request threads often expose a smaller downstream pool or increase contention on a CPU-bound application. Revert to the prior value and size concurrency to the slowest dependency rather than to the number of client connections.

Connections are refused during short bursts

Measure active threads, the accept queue, proxy limits, operating-system backlog, and file descriptors. Raise acceptCount only when the queue is the limiting factor and the rest of the path is configured to hold it. Otherwise, a larger queue can create long waits without increasing completed work.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Compression increases CPU or tail latency

Compare compressed and uncompressed response sizes by content type. Disable compression for already-compressed media and for responses where bandwidth savings do not offset CPU cost. Apply the narrower policy at the proxy or connector layer that actually handles the response.

A repeatable production checklist

  • Identify whether the service is Ubuntu’s tomcat10 package, a tarball, or another deployment.
  • Capture request, latency, error, CPU, heap, GC, queue, connection, and downstream metrics.
  • Back up the active environment, XML files, and systemd drop-ins.
  • Place JVM memory limits in CATALINA_OPTS and size them from observed live-set and total-memory headroom.
  • Confirm whether a shared executor overrides connector-level thread settings.
  • Change maxThreads, acceptCount, timeouts, keep-alive, and compression only in response to measured behavior.
  • Verify every XML attribute against the installed Tomcat version.
  • Install current Ubuntu security fixes and establish a post-update baseline.
  • Use CPU and NUMA placement only after profiling shows a placement problem.
  • Retain the configuration that improves the chosen metric without shifting failures or saturation downstream.

The practical rule is simple: make the smallest measured change that removes the current bottleneck, verify it under representative traffic, and keep a tested rollback path.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Apache TomcatJavaJVM tuningLinux performancesystemdUbuntu

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.