Organizing env vars

Originally published Jun 29, 2021

I'm working on a couple of systems using Cloudflare Workers to run some basic APIs and generate content. Workers are powerful — they're fast, run in datacenters across 200 cities, and give you access to some powerful caching capabilities built on top of Cloudflare's infrastructure.

However, in order to deliver that kind of performance, Cloudflare imposes some limits on the Workers platform. These limits include a maximum of 32 environment variables per Worker. If you're connecting to an authentication service, a database, an instrumentation server and a metrics server, this might already be using 10-12 of these variables, depending on which services you're using.

Luckily, there's a way to combine environment variables and read them using the URLSearchParams global constructor. Suppose you have the following variables set:

DATABASE_CREDENTIALS_URLENC="?key=abc123&secret=987zyx&table=mytable"

Since Workers read environment variables as globals, I've added a _URLENC suffix to denote that this is a url-encoded value. This also allows me to use the variable name DATABASE_CREDENTIALS to refer to the decoded credentials.

Using the URLSearchParams constructor allows you to read these values directly:

const DATABASE_CREDENTIALS =
  new URLSearchParams(DATABASE_CREDENTIALS_URLENC);

const db = new CloudDbProvider({
  credentials: {
    accessKey: DATABASE_CREDENTIALS.get('key'),
    secretKey: DATABASE_CREDENTIALS.get('secret'),
  },
  table: DATABASE_CREDENTIALS.get('table')
});

If you don't want to have to use .get() every time you want to read a value, you can create an object with your desired values as properties:

const DATABASE_CREDENTIALS = [
  ...new URLSearchParams(DATABASE_CREDENTIALS_URLENC).entries(),
].reduce((state, [key, value]) => ({ ...state, [key]: value }), {});

const db = new CloudDbProvider({
  credentials: {
    accessKey: DATABASE_CREDENTIALS.key,
    secretKey: DATABASE_CREDENTIALS.secret,
  },
  table: DATABASE_CREDENTIALS.table
});