Enumerations

An enum is a closed set of named states — an order's lifecycle, a product's status, a currency. You list the real states; the platform handles the wire encoding, the database type, and a safety rule that keeps enums forward-compatible.

Declaring an enum

List the members, comma-separated:

sub-domains/ordering/entities/order.vishwakarma
enum OrderStatus { PENDING, PAID, FULFILLED, CANCELLED }

An enum is then used like any other type — as a field's type, optionally with a default:

status OrderStatus required

Chowk's model is full of them: ProductStatus { DRAFT, ACTIVE, ARCHIVED }, Currency { INR, USD, SGD }, ShipmentStatus { PENDING, PICKING, DISPATCHED, DELIVERED }. Each is a small, closed vocabulary the compiler can check every reference against.

The one rule: never write the zero value

The platform automatically injects a zero member<ENUM>_UNSPECIFIED — as the first value of every enum. You list only the real states. This is what makes an enum safe to evolve: a field that was never set reads back as the explicit "unspecified" sentinel rather than silently defaulting to whatever member happened to be declared first.

Declaring the unspecified member yourself is an error, not a convenience:

// WRONG — the framework already injects the zero value.
enum OrderStatus { ORDER_STATUS_UNSPECIFIED, PENDING, PAID }

// RIGHT — list only the real states.
enum OrderStatus { PENDING, PAID, FULFILLED, CANCELLED }

Bare members in your model, prefixed on the wire

Inside the model you always refer to a member by its bare name — a default status OrderStatus = PENDING, a command guard status == 'PENDING'. On the wire, the same member is serialized in a prefixed form that includes the enum name: PENDING travels as "ORDER_STATUS_PENDING", INR as "CURRENCY_INR". So a client reading an order back sees:

{ "status": "ORDER_STATUS_PENDING", "total": { "amountMinor": "50000", "currency": "CURRENCY_INR" } }

Author with the bare member; expect the prefixed form in JSON payloads. The prefix guarantees a member name is unambiguous across every enum in the system.

What the platform generates

From one enum line you get a Postgres enum type, the wire encoding with its injected zero value, generated client constants, and compile-time checking of every reference — a guard that compares status against a member that does not exist is a build-time error, not a runtime surprise. The enum is a single declaration that the schema, the API, and the clients all derive from.