Beginner May 3, 2026 · 1 min read

The required and default flags work together: default covers cases where a value isn't provided, required ensures the field is present in storage. Pairing them is the standard pattern for status-style fields.

The pattern

- name: status
  type: select
  required: true
  default: "draft"
  options:
    - { label: Draft,  value: draft }
    - { label: Active, value: active }
    - { label: Closed, value: closed }

What this produces

  • SQL: \status` VARCHAR(100) NOT NULL DEFAULT 'draft'`
  • Go struct field: Status string \db:"status" json:"status" validate:"required"``
  • API behaviour: if a client POSTs without status, the SQL DEFAULT 'draft' clause supplies the value. The Go validate tag is satisfied because the runtime fills the field after retrieving from the database.

When default makes sense

Scenario Default Why
Status enums the initial state (draft, pending) New records haven't hit terminal states
Boolean flags false "Enabled" usually starts off
Counters / quantities 0 New records have no history
Created-by audit (handled by Loom) Don't add — runtime sets created_by

When to skip default

For fields that must come from the user (email, name, customer reference), required: true without a default is correct. The API will return HTTP 400 if the body is missing the field.

SQL escaping

Loom escapes string defaults correctly — even with embedded quotes:

- name: motto
  type: text
  default: "it's complicated"

Becomes DEFAULT 'it''s complicated' — single quotes doubled per SQL spec.

Boolean defaults

- name: send_emails
  type: boolean
  required: true
  default: true

Becomes TINYINT(1) NOT NULL DEFAULT 1.

Numeric defaults

- name: priority
  type: integer
  default: 5

Becomes BIGINT NULL DEFAULT 5 (no NOT NULL because required wasn't set).

Was this article helpful?