Varnish Controller

Known Issues

This page lists known issues with Varnish Controller. These can be identified bugs that are being worked on with potential workarounds for them. If nothing else is stated, these issues applies to all versions.

Multiple Matches of CIDR Routes

If a CIDR route has multiple entries and two or more matches an client IP, it’s currently not defined which one will be used for routing. It could be either of them. This is something that will be a defined behavior in future release of the controller.


Instead of having multiple matching entries such as and it can be resolved with multiple chained CIDR decisions. Such as cidr:1,cidr:2 in the lookup-order of the RoutingRules.

Max sequence ID reached for varnish_stat table

Note: This has been fixed in version 5.1.0.

The Varnish Controller uses the PostgreSQL UPSERT logic, a query would look like this INSERT INTO varnish_stat ON CONFLICT DO UPDATE data. These queries may cause issues after running the Varnish Controller for some time. Depending on the number of agents, Varnish statistic counters, routers, and domains you will get this error:

ERROR:  nextval: reached maximum value of sequence "varnish_stat_id_seq" (2147483647)

The error explains that the maximum value of the ID sequence has been reached, but when you look in your varnish_stat table you will see that there are not as many rows in there. This has to do with the way PostgreSQL is handling the INSERT ... ON CONFLICT .... PostgreSQL will increment the ID sequence even when the ON CONFLICT part is reached. Without actually inserting data the ID is still incremented to prevent concurrency issues. When processing the Varnish statistics we run many of these queries and eventually the Varnish Controller is running out of IDs. We are working on a proper fix for our next release, but to keep your system collecting statistics we have written a query that can be run straight into your database to reset the ID sequence.


By running the following query we are resetting all the IDs of the varnish_stat table and instructing the varnish_stat ID sequence to start counting from the real row count again. This SQL script can be ran multiple times without any problems.

-- Use the same advisory lock as we do when inserting statistics to prevent concurrency
-- This is a transactional advisory lock which is automatically unlocked upon rollback or commit
SELECT pg_advisory_xact_lock(4011117430);

DO $$
    statrec record;
    i int = 0;
    -- Loop over all varnish_stat records
    for statrec in
      SELECT * FROM varnish_stat ORDER BY id
      -- PSQL loops do not have indexes build in so we build our own index which is also our new ID
      i := i+1;

      -- First update the values tables as those will be updated automatically when we update the varnish_stat table
      IF != i THEN
        UPDATE varnish_stat_values_1m SET varnish_stat_id = i WHERE varnish_stat_id =;
        UPDATE varnish_stat_values_10m SET varnish_stat_id = i WHERE varnish_stat_id =;
        UPDATE varnish_stat_values_1h SET varnish_stat_id = i WHERE varnish_stat_id =;
        UPDATE varnish_stat_values_1d SET varnish_stat_id = i WHERE varnish_stat_id =;
        UPDATE varnish_stat_values_1mo SET varnish_stat_id = i WHERE varnish_stat_id =;
        UPDATE varnish_stat SET id = i WHERE id =;
        RAISE NOTICE 'Updated counter: % from ID % to ID %',,, i;
      END IF;
    end loop;

    -- After we have updated the records we reset the sequence to start from the last ID number
    -- we add 1 as the last value of i is the last ID of the counter we used. So if the last counter has ID
    -- 100 we want the sequence to restart at 101.
    i := i+1;
    RAISE NOTICE 'Restart varnish_stat_id_seq sequence from %', i;
    execute 'ALTER SEQUENCE varnish_stat_id_seq RESTART WITH ' || i;

-- Transactional lock is automatically unlocked after commit or rollback


Same Domain for Multiple VCLGroups (Request Routing)

Only one VG can be deployed for the same domain to the router for it to be routed correctly. The router only knows about the domain of incoming requests and can currently not distinguish between different VCLGroups with the same domain. It will not know to which one the request should be routed to.


In order to route to a different set of servers such as Edge first, then Storage as fallback. One can create a second VCLGroup with a different domain, say and use that as an External Route and use the External Route as a fallback in the first Routing Rule for the first VCLGroup. This will create an extra HTTP 302 redirect, but only when the first VCLGroup has no available servers.

- VCLGroup1
    - Domain:
    - RoutingRule: rr1
        - Lookup-order: <decision>,external
        - ExternalRoutes: ext1
            - URL:
- VCLGroup2
    - Domain:
    - RoutingRule: rr2
        - Lookup-order: <decision>