Varnish Controller

Known Issues

This page lists known issues with Varnish Controller; for example, identified bugs that are being worked on, along with potential workarounds. If not stated, these issues apply to all versions.

VCLGroup fails to compile in 6.1.0

In version 6.1.0, the Varnish Controller Agent sets the TMPDIR variable to match the base-dir of the agent. This causes varnishtest to fail if the path gets too long. To resolve this, please upgrade to version 6.1.1.

Missing permissions in 6.0.0

In Version 6.0.0, a more stringent permission check was introduced, resulting in cases where users may find certain permissions missing. If there’s no router license available, these permissions won’t be visible in the controller UI. We’re actively working to address this issue, but as an immediate fix, you can add the necessary permissions using the CLI.

Verify necessary permissions

vcli perms requirements

Add missing read permissions for the required resource

vcli perms add <permission> -a <account-id> -o <organization-id> --read


If the RegexpRoute permission is missing for an account with “ID: 2” within an organization with “ID: 1”, use the following commands:

vcli perms add regexproute -a 2 -o 1 --read
vcli perms add regexptag -a 2 -o 1 --read

These will add the necessary read permissions for the specified account and organization.

Unable to migrate Version v400

Note: This issue has been addressed in Version 5.3.1.

Varnish Controller uses SQL scripts to migrate from version to version. Release 5.3.0 contains a bug with migrations that will cause a duplicate key error - a data discrepancy that was created with the release of Version 4.0.0. Only Varnish Controller versions running prior to 4.0.0 may receive the following startup error when upgrading Brainz to 5.3.0:

failed to migrate DB: cannot migrate version v400: pq: duplicate key value violates unique constraint "varnish_stat_uniq"

The changes in Version 4.0.0 cause the varnish_stat table to return duplicates for all rows that were in the table at that time. To resolve this error, you must delete the duplicate rows that are no longer in use.

DELETE FROM varnish_stat WHERE router_id IS NULL AND domain_id IS NULL;

Max sequence ID reached for varnish_stat table

Note: This issue has been addressed in Version 5.1.0.

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 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’ll see that there aren’t 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 many of these queries and, eventually, Varnish Controller run out of IDs. To keep your system collecting statistics, we’ve written a query that can be run straight into your database to reset the ID sequence.

By running the following query, you can reset the IDs in the varnish_stat table and instruct the varnish_stat ID sequence to start counting from the real row count again. This SQL script can be run 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 don't have indexes built-in, so build your own index which is also your new ID
      i := i+1;

      -- First update the values tables, as those will be updated automatically when updating 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 updating the records, you reset the sequence to start from the last ID number
    -- Add 1; the last value of i is the last ID of the counter you used. So if the last counter has ID
    -- 100, you'll 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 within the same domain. It won’t know which one the request should be routed to.

To route to a different set of servers (like Edge first, then Storage as fallback), create a second VCLGroup with a different domain, like Use it 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>