Aug 18

Why We Switched from YAML to TypeScript for Our Configuration

Stellate is being used to speed up, scale, and monitor GraphQL APIs across many industries, from e-commerce stores and marketplaces to travel platforms, political advocacy websites, and music magazines.

To support all of these vastly different use-cases and their individual caching requirements, we need configuration, and that configuration needs to be as simple and usable as possible. When we originally built the GraphQL Edge Cache, we considered several static configuration formats, including YAML, JSON, and TOML.

Given that JavaScript is the most widely used language with GraphQL, we wanted to optimize for familiarity for JavaScript developers, which left us deciding between JSON and YAML.

Choosing between those two came down to creating example configurations and looking at them side-by-side. We (honestly, totally subjectively) thought YAML was more readable than JSON for our configuration and went with YAML.

If you’re already using Stellate for your GraphQL API, you’ve edited a stellate.yml file many times. However, after a year of evolving our product, we realized that YAML falls short in flexibility for our use case.

Why We Switched to TypeScript

Specifically, YAML doesn’t allow us to use more powerful programming language constructs like functions, which we need for some advanced features we’re planning (like edge invalidation functions), and is difficult to modularize when larger companies want to share responsibility for different parts of the configuration between different teams.

It’s also white-space sensitive, which is unnecessarily error-prone, it’s not type-safe, so we have to manually build basic validation for everything, and it doesn’t have editor autocomplete for our configuration shape.

So, we switched our configuration to be based on TypeScript instead!

Having your configuration in a stellate.ts file allows you to have:

  • Modularity ✅

  • White-space insensitivity ✅

  • Type-safety ✅

  • Editor autocomplete ✅

On top of that, TypeScript being an actual programming language means that we’ll be able to use its full power for future features, and you’re able to leverage the full power of its immense ecosystem of packages. I mean, just look at this! chef kiss

import { Config } from 'stellate';
const PUBLIC_TYPES = ['MarketingContent', 'Product']
const PRIVATE_TYPES = ['Cart', 'User']
const PREVIEW_HEADERS = ['cms-preview']
const stellate: Config = {
config: {
name: 'my-awesome-store',
schema: './schema.graphql',
originUrl: 'https://ecommerce.store',
enablePlayground: false,
queryDepthLimit: 5,
mutationPolicy: 'List',
bypassCacheHeaders: PREVIEW_HEADERS.map(name => ({ name })),
scopes: {
AUTHENTICATED: 'header:authorization'
},
rules: [
{
description: 'All publicly accessible types'
types: PUBLIC_TYPES,
maxAge: 900,
swr: 3600
},
{
description: 'All private types'
types: PRIVATE_TYPES,
scope: 'AUTHENTICATED'
maxAge: 900,
swr: 3600
},
]
}
}

Finally, we also recently introduced universal configuration-as-code from your browsers to your terminal, which means you’ll be working with the exact same stellate.ts file no matter where you’re configuring your Stellate service.