DEV Community

Alex Spinov
Alex Spinov

Posted on

Pkl Has a Free API: Apple's Configuration Language That Catches Errors Before Your App Starts

YAML has no types. JSON has no comments. TOML is too simple for complex configs. Pkl, created by Apple, is a configuration language that validates your config at generation time — catch errors before deployment, not in production.

What Is Pkl?

Pkl (pronounced "pickle") is a configuration language from Apple. It has a type system, validation constraints, and generates output in any format: JSON, YAML, TOML, XML, or Java properties. Think of it as TypeScript for configuration files.

Why Pkl Is Different

  • Type system: Catch invalid configs at generation time
  • Constraints: Validate values (port must be 1-65535)
  • Multi-format output: Generate JSON, YAML, TOML from one source
  • Modules: Reuse config across projects
  • IDE support: VSCode extension with autocomplete
  • Code generation: Generate TypeScript, Go, Java, Swift types from schemas
  • Completely free and open source (by Apple)

Quick Start

Install Pkl:

brew install pkl
Enter fullscreen mode Exit fullscreen mode

Write a config:

// config.pkl
module AppConfig

host: String = "localhost"
port: UInt16 = 3000
database {
  host: String = "db.example.com"
  port: UInt16 = 5432
  name: String = "myapp"
  maxConnections: UInt8(isBetween(1, 100)) = 20
}
redis {
  host: String = "redis.example.com"
  port: UInt16 = 6379
  ttl: Duration = 1.h
}
featureFlags {
  darkMode: Boolean = true
  betaUsers: Boolean = false
}
Enter fullscreen mode Exit fullscreen mode

Generate JSON:

pkl eval config.pkl -f json
Enter fullscreen mode Exit fullscreen mode

Output:

{
  "host": "localhost",
  "port": 3000,
  "database": {
    "host": "db.example.com",
    "port": 5432,
    "name": "myapp",
    "maxConnections": 20
  },
  "redis": {
    "host": "redis.example.com",
    "port": 6379,
    "ttl": "1h"
  }
}
Enter fullscreen mode Exit fullscreen mode

Type safety catches errors:

// This FAILS at generation time:
port: UInt16 = 99999  // Error: 99999 is not UInt16 (max 65535)
database {
  maxConnections: UInt8(isBetween(1, 100)) = 200  // Error: 200 > 100
}
Enter fullscreen mode Exit fullscreen mode

Generate TypeScript types:

pkl-gen-typescript config.pkl
Enter fullscreen mode Exit fullscreen mode

Why Developers Choose Pkl

A DevOps team managed 50+ microservice configs in YAML. A typo in a database port ("54322" instead of "5432") caused a 2-hour outage. After migrating to Pkl with typed schemas, invalid configs were caught instantly at generation time. They have not had a config-related outage since.

Who Is This For?

  • DevOps engineers managing complex multi-service configs
  • Teams tired of YAML bugs causing production outages
  • Developers wanting IDE autocomplete for configuration
  • Anyone who has been burned by a typo in a config file

Start Using Pkl

Pkl brings type safety to configuration. Catch errors at generation time, not after deployment.

Need help with configuration management? I build custom DevOps solutions — reach out to discuss your project.


Found this useful? I publish daily deep-dives into developer tools and APIs. Follow for more.

Top comments (0)