Stop Burning Cash on Slow Builds: Optimizing CI/CD with Jenkins and SSD VPS
I walked into a client's office in Oslo last week and saw something that made my blood boil. Three senior backend engineers were sitting around the coffee machine, debating the merits of the new Game of Thrones season. I asked them why they weren't pushing the hotfix for the payment gateway. The lead dev shrugged and pointed to a monitor displaying a Jenkins progress bar crawling at a glacial pace. "We're waiting for the integration tests. It takes 45 minutes."
45 minutes. That is not a pipeline; that is a sewer clog. In the era of agile development, if your feedback loop is longer than a coffee break, you are bleeding money. The bottleneck is rarely your code complexity—it is almost always your infrastructure.
Let’s cut through the marketing fluff. I’m going to show you how to rip out the inefficiencies in your Continuous Integration setup using tools we actually trust in production—Jenkins, Ansible, and high-performance KVM virtualization.
The Silent Killer: Disk I/O Wait
Most VPS providers in Europe try to sell you on CPU cores. "Get 16 vCPUs!" they shout. But when you run a heavy build process—compiling Java classes, building RPMs, or running a MySQL integration test suite—your CPU is often sitting idle, waiting for the disk to write data. This is iowait, and on standard magnetic storage (HDD), it is the death of speed.
When you run top during a build, if your %wa (wait) is over 10%, your storage is too slow.
We recently migrated a Magento build pipeline from a budget host in Germany to a CoolVDS instance here in Norway. The previous host used shared SAN storage. CoolVDS provided local SSD storage. The result? The `mvn clean install` time dropped from 14 minutes to 3 minutes. No code changes. Just better physics.
Optimization #1: RAM-Disk for Test Databases
If you are running automated tests that require a database, you are likely creating and dropping tables thousands of times. Doing this on disk is madness. For ephemeral test data, use tmpfs (RAM disk). It is volatile, but who cares? It's a test run.
Here is how to mount a 2GB RAM disk for your MySQL test instance on CentOS 6:
mkdir -p /var/lib/mysql/tmp_ram
mount -t tmpfs -o size=2G tmpfs /var/lib/mysql/tmp_ram
chown mysql:mysql /var/lib/mysql/tmp_ram
Then, tweak your my.cnf to point the datadir there, or simply use it for temporary tables. Furthermore, for test environments, you should disable ACID compliance to prioritize speed over safety. You don't need crash recovery for a Jenkins job.
[mysqld]
# DANGER: ONLY FOR TEST ENVIRONMENTS
innodb_flush_log_at_trx_commit = 0
innodb_doublewrite = 0
sync_binlog = 0
innodb_buffer_pool_size = 1G
Latency Matters: The NIX Advantage
If your team is in Oslo but your build server is in Virginia, you are fighting the speed of light. Every git fetch, every scp, and every SSH handshake adds delay.
Hosting within Norway isn't just about patriotism or meeting Datatilsynet requirements (though keeping customer data within the EEA is critical post-Snowden). It is about the Norwegian Internet Exchange (NIX). When your VPS is peered directly at NIX, like CoolVDS instances are, your latency to local ISPs drops to sub-5ms.
Pro Tip: Use a local repository mirror. If you are constantly pulling dependencies from Maven Central or npm, set up a Nexus or Artifactory instance on a separate CoolVDS VPS on the same private LAN. Transferring artifacts over a private Gigabit LAN is significantly faster than pulling them over the public WAN every time.
Master-Slave Architecture with Jenkins
Stop running builds on the Jenkins master. The master is for scheduling and orchestration. Heavy lifting belongs on slaves. This ensures that if a build goes rogue and eats all memory, your dashboard remains accessible.
We use SSH slaves. It is cleaner than JNLP and requires no firewall gymnastics if you have standard SSH access. Here is a robust way to ensure your build environment is clean using Ansible before a build starts. This playbook ensures your slave has the necessary packages:
---
- hosts: jenkins_slaves
user: root
tasks:
- name: Ensure Java JDK 1.7 is installed
yum: name=java-1.7.0-openjdk state=installed
- name: Install Git
yum: name=git state=latest
- name: Clean up old artifacts to free inodes
shell: find /tmp/ -user jenkins -mtime +2 -exec rm -rf {} \;