# Pool your RabbitMQ connections with AMQProxy

> Stop opening a new broker connection on every request. AMQProxy keeps connections open and hands them out, which cuts publish latency and takes load off your broker.

## Pool your RabbitMQ connections with AMQProxy

PHP cannot hold a connection open between requests. So every request that publishes a message opens a connection to your broker, does a handshake, sends one small message, and tears the connection down again. That handshake costs at least seven round trips, and eighteen packets once TLS is involved.

AMQProxy sits between your application and the broker. It keeps the connections open, hands out pooled channels, and lets many client connections share a single connection to the broker. Your application still connects on every request, but it connects to the proxy, which is already holding a warm connection.

Two situations where it pays off:

- **Your broker is far away.** This is the big one. On a broker with 50ms of round trip time, publishing one message per connection takes around 500ms without the proxy and around 10ms with it. The TLS handshake also happens once instead of on every request.
- **Your broker is close, but busy.** With a RabbitMQ service in the same application the latency is already tiny, so you will not notice a speed difference. What you get instead is far fewer connections. Every connection costs your broker memory, and a busy PHP application can churn through thousands of them a minute.

### Adding it

1. Go to your application and add a new service.
2. Pick **AMQProxy** under Queue.
3. Choose how much memory it gets. It is a small process, so the smallest size is usually plenty.
4. Leave **AMQP_URL** empty if you have a RabbitMQ service in this application. The proxy finds it on its own.

That is enough to get it running. Adding it does not change anything about how your application connects yet, which is deliberate: nothing gets rerouted behind your back.

### Sending your traffic through it

You have two ways to do this.

**Let us repoint it for you.** Set **REWRITE_RABBITMQ_VARIABLES** to `true`. Your application's `RABBITMQ_HOST`, `RABBITMQ_PORT` and `RABBITMQ_URL` will point at the proxy from the next deployment, and everything else stays as it was. Your username and password do not change. This only works when the broker is a RabbitMQ service in the same application.

**Do it yourself.** Leave the rewrite off and use the variables the proxy adds:

- `AMQPROXY_HOST` is the proxy's hostname
- `AMQPROXY_PORT` is `5673`
- `AMQPROXY_URL` is the two combined

Point whatever configuration your application uses at those. This is the route to take if your connection details live in your own secrets, or if your application reads variables we do not know about.

Either way, roll it out during a quiet moment. Existing connections are not migrated; your application picks up the new address when it next deploys.

### Using an external broker

If your broker is hosted elsewhere, for example on CloudAMQP, put its address in **AMQP_URL** and skip the rewrite setting. This is where the proxy earns its keep, so it is worth the extra setup.

Four things to know:

- **Give the address only.** Scheme, host and port, like `amqps://kangaroo.rmq.cloudamqp.com:5671`. Anything else in that address is ignored.
- **Credentials stay with your application.** The proxy does not log in for you. Your application keeps sending its own username, password and vhost, exactly as it does today. This surprises people who paste the full connection string their provider gave them and expect it to authenticate.
- **Allowlist our addresses.** If your provider restricts access by IP, add our address ranges. You can fetch the current ranges per region from the `/api/v1/cluster/ip-ranges` endpoint.
- **Watch your plan's channel limit.** Hosted plans usually cap connections and channels. Pooling is what keeps you under a connection cap, but set **MAX_UPSTREAM_CHANNELS** below whatever your plan allows for channels, or the broker will start refusing them.

Use `amqps://` for anything crossing the public internet. The proxy handles the encryption to your broker, and it only trusts publicly issued certificates, so a broker using a private certificate authority will not work.

### Tuning

- **IDLE_CONNECTION_TIMEOUT** is how many seconds an unused pooled connection is kept before it is closed. The default of 5 suits most applications. Raise it if your traffic comes in bursts with quiet gaps, so the pool is still warm when the next burst arrives.
- **MAX_UPSTREAM_CHANNELS** is the ceiling on channels per connection to the broker. Leave it alone unless your broker caps channels.
- **LOG_LEVEL** set to `debug` will show you each connection as it is opened and reused. Useful when you are checking that pooling is doing what you expect, noisy otherwise.

### Checking it works

Open the service logs. On startup the proxy prints the broker it is pooling for, which is the quickest way to catch a wrong address.

The clearest sign it is working is on the broker side: connection count goes flat and stays low while your traffic carries on as normal. Before the proxy, that number climbs with every request.

### What to watch out for

- **Everything goes through it.** Once your application points at the proxy, the proxy is in the path of every message you publish. Running two of them is worth considering for a busy application: they share the work, and losing one no longer stops your publishing.
- **It restarts when you change its settings.** Changing a setting restarts the proxy, which drops the connections it is holding. Clients reconnect, but any message in flight at that moment is not retried for you.
- **It does not fix a broken broker.** If the broker is down, the proxy is up and healthy and your messages still fail. The proxy is a connection pool, not a queue.
