WARNING:

This website has been archived. All new documentation and updates will be focused on the new domain, https://vexilla.dev

Caching

On your server, you probably want to cache the Vexilla Flags and config. This can save your users time. It can save your bandwidth costs.

Long Polling

One quick and easy way of keeping the cache up to date is long-polling. This involves just fetching from your static hosting on an interval and updating the cache.

Be warned that this can introduce lag time between changing a flag and when it gets updated on your server/client. In most cases, that is acceptable, but entirely depends on the length of your timer.

Here is a quick example of an Express.js based server and its long-polling mechanism:

const express = require("express");
const app = express();
const port = 3000;
const VexillaClient = require("@vexilla/client");
const fiveMinutes = 1000 * 60 * 5;
let flags = {};
const globalVexillaClient = new VexillaClient({
baseUrl: "https://BUCKET_NAME.s3-website-AWS_REGION.amazonaws.com",
environment: process.env.ENVIRONMENT,
// for the global fetch, we don't need the user or instance ID
customInstanceHash: null,
});
// first fetch
fetchFlags();
// recurring fetches
setInterval(fetchFlags, fiveMinutes);
app.get("/hello", (req, res) => {
const localVexillaClient = new VexillaClient({
baseUrl: "https://BUCKET_NAME.s3-website-AWS_REGION.amazonaws.com",
environment: process.env.ENVIRONMENT,
// relies upon user being set by middleware
customInstanceHash: req.user.id,
});
localVexillaClient.setFlags(flags);
if (localVexillaClient.should("SayHello")) {
res.send("Hello World!");
} else {
res.status(500).send("Something broke!");
}
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
async function fetchFlags() {
flags = await globalVexillaClient.fetchFlags("features.json");
}

Lazy Loading

This technique is very similar to the long-polling above. The main difference is that it does not continuously fetch the flags.

There are some trade-offs. You will save on bandwidth requesting the flags. However, when the cache is expired, a request pays an extra cost while waiting for the flags to update if you want them to have the latest flags.

If you are ok serving stale flags to this first user, they will just not get the update and instead the next request does. While stale data might not be ideal, a long request time could be worse in some cases such as when you have MANY feature flags.

const express = require("express");
const app = express();
const port = 3000;
const VexillaClient = require("@vexilla/client");
const fiveMinutes = 1000 * 60 * 5;
let flags = {};
let lastFlagFetch = 0;
const globalVexillaClient = new VexillaClient({
baseUrl: "https://BUCKET_NAME.s3-website-AWS_REGION.amazonaws.com",
environment: process.env.ENVIRONMENT,
// for the global fetch, we don't need the user or instance ID
customInstanceHash: null,
});
// first fetch
fetchFlags();
app.get("/hello", async (req, res) => {
const localVexillaClient = new VexillaClient({
baseUrl: "https://BUCKET_NAME.s3-website-AWS_REGION.amazonaws.com",
environment: process.env.ENVIRONMENT,
// relies upon user being set by middleware
customInstanceHash: req.user.id,
});
// This is the main thing that changes
if (lastFlagFetch + fiveMinutes < Date.now()) {
// update fetch timestamp
lastFlagFetch = Date.now();
// update global flags
flags = await localVexillaClient.fetchFlags("features.json");
}
localVexillaClient.setFlags(flags);
if (localVexillaClient.should("SayHello")) {
res.send("Hello World!");
} else {
res.status(500).send("Something broke!");
}
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
async function fetchFlags() {
flags = await globalVexillaClient.fetchFlags("features.json");
}