Eliminate TCP handshake overhead. Reuse database connections.
Laravel opens a new database connection for every request (unless you're using Octane). This means 1-3ms of TCP handshake + authentication per request. For 10,000 requests per minute, that's 10-30 seconds of pure overhead. ProxySQL eliminates this completely.
ProxySQL reduces database connection latency by 90-95%. Instead of 1.5ms per request, you pay 0.1ms. For high-traffic Laravel apps, this is a massive win.
# Ubuntu/Debian
wget -O - 'https://repo.proxysql.com/ProxySQL/repo_pub_key' | sudo apt-key add -
echo "deb https://repo.proxysql.com/ProxySQL/proxysql-2.6.x/ubuntu/$(lsb_release -sc) ./" | sudo tee /etc/apt/sources.list.d/proxysql.list
sudo apt update
sudo apt install proxysql
# Start ProxySQL
sudo systemctl enable proxysql
sudo systemctl start proxysql
# Connect to ProxySQL admin interface
mysql -u admin -padmin -h 127.0.0.1 -P 6032
# Default credentials: admin:admin
# Change password immediately!
-- Add MySQL servers to ProxySQL
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (1, 'master.db.example.com', 3306);
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (2, 'replica1.db.example.com', 3306);
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (2, 'replica2.db.example.com', 3306);
-- Hostgroup 1 = Writes (Master)
-- Hostgroup 2 = Reads (Replicas)
-- Load configuration
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
-- Send SELECT queries to hostgroup 2 (replicas)
INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply)
VALUES (1, 1, '^SELECT', 2, 1);
-- Send everything else (INSERT, UPDATE, DELETE) to hostgroup 1 (master)
INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply)
VALUES (2, 1, '^INSERT|^UPDATE|^DELETE', 1, 1);
-- Load rules
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
-- Add MySQL user for application
INSERT INTO mysql_users (username, password, default_hostgroup)
VALUES ('laravel_user', 'strong_password', 1);
-- Load users
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
# .env
# Point Laravel to ProxySQL instead of direct MySQL
DB_HOST=127.0.0.1 # ProxySQL runs locally
DB_PORT=3306 # Standard MySQL port (ProxySQL listens here)
DB_DATABASE=laravel
DB_USERNAME=laravel_user
DB_PASSWORD=strong_password
Laravel doesn't know it's talking to ProxySQL. It thinks it's talking directly to MySQL. The only change is the DB_HOST (pointing to ProxySQL instead of your database server).
| Metric | Without ProxySQL | With ProxySQL | Improvement |
|---|---|---|---|
| Connections per request | 1 (new connection) | 0.01 (reused connection) | 99% fewer connections | TCP handshake per request | 1 (1-2ms) | 0 (0ms) | 100% eliminated |
| MySQL authentication per request | 1 (0.3-0.5ms) | 0 (0ms) | 100% eliminated |
| Total connection overhead (10k req) | ~15 seconds | ~1 second | 93% reduction |
| Max concurrent MySQL connections | = PHP-FPM processes (e.g., 100) | = ProxySQL pool size (e.g., 20) | 5x fewer DB connections |
MySQL has a max_connections limit (default 151). Without ProxySQL, each PHP-FPM process needs a connection. With 100 PHP-FPM children, you need 100 MySQL connections. With ProxySQL, you only need 20-30 persistent connections, regardless of PHP-FPM count.
For repetitive queries (e.g., `SELECT * FROM settings`), ProxySQL query cache can serve responses in 0.5ms vs 10ms from MySQL β a 20x improvement.
# Connect to admin interface
mysql -u admin -padmin -h 127.0.0.1 -P 6032
# Check connection pool status
SELECT * FROM stats_mysql_connection_pool;
# Check query statistics
SELECT * FROM stats_mysql_query_digest ORDER BY count_star DESC LIMIT 10;
# Check query cache hits
SHOW STATUS LIKE 'QUERY_CACHE%';
# Check connection pool size
SELECT hostgroup, srv_host, srv_port, status, ConnUsed, ConnFree
FROM stats_mysql_connection_pool;
# Check slow queries
SELECT * FROM stats_mysql_query_digest WHERE avg_query_time > 1000;
Monitor these metrics in production:
Topic 20: APCu vs Redis β Local shared memory vs network-based cache. When to use APCu for tiny, fast-changing data. When Redis is the right choice.