Skip to content

Scope & Namespaces ​

As your Carotene application grows, organizing your primitives into distinct, bounded contexts becomes essential. Carotene provides a simple, optional mechanism for this: the domain block.

The Global Namespace ​

By default, if you do not wrap your .carrot definitions in a domain block, everything belongs to the Global Namespace.

dart
// Global Namespace
model User {
  id: UUID
  email: String
}

backend API {
  store Users { model: User }
}

The Global Namespace is perfect for small projects, simple prototypes, or monolithic applications where naming collisions are unlikely.

The domain Block ​

When building larger applications or adhering to Enterprise Domain-Driven Design (DDD), you can use the domain block to explicitly scope your primitives.

The domain block acts purely as an organizational namespace. It clarifies ownership and enforces strict microservice isolation, ensuring that a primitive inside one domain does not accidentally clash with a primitive of the same name in another domain.

dart
domain Commerce {
  model Order {
    id: UUID
    total: Float
  }

  backend OrderAPI {
    store Orders { model: Order }
  }
}

domain Fulfillment {
  // Safe: Does not collide with Commerce.Order
  model Order {
    id: UUID
    shippingAddress: String
  }
}

Why use domain? ​

  1. Microservice Isolation: By scoping backends and stores within a domain, you establish clear boundaries. One domain cannot implicitly couple itself to the internal data structures of another without explicit, cross-boundary calls.
  2. Naming Collision Prevention: In large monorepos with multiple teams, using domains like Billing, Identity, and Inventory allows teams to use common names (like User or Account) without stepping on each other's toes.
  3. Enterprise DDD: The domain block maps perfectly to bounded contexts in Domain-Driven Design, making your .carrot files a 1:1 reflection of your business architecture.

NOTE

The domain block is a compile-time organizational feature. It does not strictly dictate your generated folder structure or deployment architecture, but rather establishes strict lexical scoping for the Carotene compiler.