Example apps
Every SDK repository has a runnable example: the same small service, orders, built with that language's usual tools. Most are HTTP services; the COBOL one is a batch job, run as a Kubernetes CronJob. Comparing them shows how each SDK fits its host library while producing the same kind of contract.
Each example:
- declares its configuration with the SDK, in the host library's own style;
- shows its typed values with the secret redacted: the HTTP services on
GET /config, besideGET /healthz, and the batch job in its output; - commits the
contract.cueit exports, and CI checks that it is up to date and passescue vet; - fails at startup with every problem listed, each with an error code, when the configuration is wrong.
The configuration
| Variable | Type | Rules |
|---|---|---|
| PORT | int | 1–65535, default 8080 |
| LOG_LEVEL | enum | debug, info, warn, error; default info |
| DATABASE_URL | url | secret, required, scheme postgres |
| ALLOWED_ORIGINS | list of strings | at least 1 item; default http://localhost:3000 |
| REQUEST_TIMEOUT | duration | 1s–5m, default 30s |
| WORKER_COUNT | int | 1–64, default 4 |
Environment variable names follow each host's conventions. Most examples read PORT; .NET reads ORDERS__PORT and Java (Spring Boot) reads ORDERS_PORT, from an Orders options section. The Laravel example reads ORDERS_LOG_LEVEL, because Laravel itself reads LOG_LEVEL. Each contract lists the exact names.
Side by side
Pick two SDKs and compare the declaration, the contract it exports, or what the app prints when PORT=0 and DATABASE_URL is missing. The code is copied from each repository's main branch, and CI fails when a copy goes stale.
// Package config is the orders service's configuration: an ordinary
// caarlos0/env struct with docuconf's tags. It lives in its own package
// because `docuconf export` imports it, and package main cannot be imported.
package config
import (
"time"
"github.com/docuconf/docuconf-go"
)
// Config is everything the orders service reads at boot.
// Doc comments become the descriptions in the contract: the first
// paragraph is the description, and any later paragraphs are its details.
type Config struct {
// HTTP listen port.
Port int `env:"PORT" envDefault:"8080" min:"1" max:"65535"`
// Minimum log level emitted.
LogLevel string `env:"LOG_LEVEL" envDefault:"info" values:"debug,info,warn,error"`
// Postgres connection string for the orders database.
DatabaseURL docuconf.Secret `env:"DATABASE_URL,required" schemes:"postgres" maxLength:"2048"`
// Origins allowed to call the API from a browser.
AllowedOrigins []string `env:"ALLOWED_ORIGINS" envDefault:"http://localhost:3000" minItems:"1"`
// Time limit for handling one request.
RequestTimeout time.Duration `env:"REQUEST_TIMEOUT" envDefault:"30s" min:"1s" max:"5m"`
// Number of background workers processing orders.
//
// Each worker holds one database connection, so keep it below the
// database's connection limit divided by the number of replicas.
// Raise it when the order queue grows faster than it drains.
WorkerCount int `env:"WORKER_COUNT" envDefault:"4" min:"1" max:"64"`
// Certificate to serve HTTPS with. Without it, the service serves HTTP.
TLS docuconf.TLSKeyPair `file:"serving-tls" path:"/etc/orders/tls" dnsNames:"orders.example.com" minRemaining:"720h" reload:"watch"`
// Discount codes accepted at checkout.
Discounts docuconf.ConfigFile[Discounts] `file:"discounts" path:"/etc/orders/discounts/discounts.yaml"`
}
// Discounts is the content of the discounts file.
type Discounts struct {
// Percent off for each discount code.
Codes map[string]int `json:"codes" yaml:"codes"`
}// The service's configuration: a T3 Env declaration with docuconf's helpers
// for what Zod has no word for (secrets, URL schemes, durations, lists).
import { z } from "zod";
import { createEnv, duration, list, secret, url } from "@docuconf/t3";
export const env = createEnv({
name: "orders",
server: {
PORT: z.coerce.number().int().min(1).max(65535).default(8080).describe("Port the HTTP server listens on"),
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("info").describe("Minimum log level emitted"),
DATABASE_URL: secret(url({ schemes: ["postgres"], maxLength: 2048 })).describe("Postgres connection string for the orders database"),
ALLOWED_ORIGINS: list(z.string(), { minItems: 1 })
.default(["http://localhost:3000"])
.describe("Comma-separated CORS origins allowed to call the API"),
REQUEST_TIMEOUT: duration({ min: "1s", max: "5m", default: "30s" }).describe("Timeout for a single request"),
/**
* Number of background order workers.
*
* Each worker holds one database connection, so keep this below the
* pool size of {@link DATABASE_URL}'s server.
*
* - Raise it when the order queue backs up.
* - Lower it when the database is the bottleneck.
*/
WORKER_COUNT: z.coerce.number().int().min(1).max(64).default(4).describe("Number of background order workers"),
},
runtimeEnv: process.env,
// On invalid configuration: print every problem and exit 1.
exitOnError: true,
});The examples
- Go · net/httpdocuconf-go/examples/orders
- TypeScript (T3 Env) · T3 Envdocuconf-js/examples/orders-t3
- TypeScript (NestJS) · NestJSdocuconf-js/examples/orders-nestjs
- .NET · ASP.NET Coredocuconf-dotnet/examples/orders
- Python · http.serverdocuconf-python/examples/orders
- Ruby · Rackdocuconf-ruby/examples/orders
- Java (Spring Boot) · Spring Bootdocuconf-java/examples/orders
- Kotlin · JDK HttpServerdocuconf-kotlin/examples/orders
- Rust · std::netdocuconf-rust/examples/orders
- Swift · POSIX socketsdocuconf-swift/Examples/Orders
- Elixir · :httpddocuconf-elixir/examples/orders
- Gleam · wispdocuconf-gleam/examples/orders
- C++ · cpp-httplibdocuconf-cpp/examples/orders
- PHP (Laravel) · Laraveldocuconf-php/examples/orders
- PHP (Symfony) · Symfonydocuconf-php/examples/orders-symfony
- COBOL · batch jobdocuconf-cobol/examples/orders
To deploy one, the platform validates its contract.cue before the pod starts, with docuconf vet and docuconf render or the Helm library chart. See How it works.