Guides

Adopting semantic types

​
Introducing Semantic Types

Evolution, Not Revolution

Successfully adopting semantic types is an incremental process. Start small, demonstrate value, then expand gradually.

​
Getting Started

Begin by identifying a focused use case:

  • Find two systems that exchange similar data
  • Identify overlapping concepts between their models
  • Create shared semantic types for these concepts

Example:

// System A's original model
model CustomerA {
    id: String
    email: String
}

// System B's original model
model CustomerB {
    customerId: String
    emailAddress: String
}

// Create shared semantic types
type CustomerId inherits String
type EmailAddress inherits String

// Refactor models to use semantic types
model CustomerA {
    id: CustomerId
    email: EmailAddress
}

model CustomerB {
    customerId: CustomerId
    emailAddress: EmailAddress
}

​
Project Organization

Separate Types from Models

Types are meant to be shared across systems, while models are system-specific. Your project structure should reflect this separation.

​
File Organization

Start with a simple separation:

src/
  types/           # Shared semantic types (your taxonomy)
    customer.taxi
    order.taxi
  models/          # System-specific models
    service-a/
      customer-model.taxi
      service-definitions.taxi
    service-b/
      customer.api.taxi # A REST API exposing customer details. Has both model and services defined

As your taxonomy grows, consider moving types to their own project:

projects/
  common-taxonomy/     # Shared semantic types
  service-a/          # Service A implementation
    dependencies:
      - common-taxonomy
  service-b/          # Service B implementation
    dependencies:
      - common-taxonomy

​
File naming conventions

​
Types

Define semantic types on their own, in a file named around the domain they model. For example:

  • customer.types.taxi
  • account.types.taxi

Also consider...

You may also wish to consider adopting separate namespaces, which further help keep concepts seperated.

​
Services and Models

Define services and models together, in the same file. Name the file after the type of service.

eg:

  • trades.kafka.taxi
  • account-events.kafka.taxi
  • customer.api.taxi
  • account.database.taxi

​
Mature Implementation Architecture

The Big Picture

A well-implemented Taxi ecosystem has clear separation between shared semantics and system-specific implementations.

A mature implementation typically includes:

​
Shared Taxonomy

  • Collection of semantic types
  • Broadly shared across organization
  • Version controlled and carefully governed
  • Published as a reusable package

​
Service Implementations

  • Models and service definitions using types from taxonomy
  • System-specific structures
  • Published to TaxiQL server (like Orbital)
  • Each service depends on shared taxonomy

​
Data Consumers

  • Import shared taxonomy only
  • Don’t depend on service-specific models
  • Query data using TaxiQL
  • Receive data mapped to their needs

​
Example workflow:

// In shared taxonomy
type CustomerId inherits String
type EmailAddress inherits String

// In service implementation
service CustomerService {
    operation getCustomer(CustomerId): Customer
}

// Consumer query using TaxiQL
find { Customer } as {
    id: CustomerId
    contact: EmailAddress
}

​
Best Practices

​
Type Development

  • Focus on business concepts
  • Keep types focused and single-purpose
  • Document type meanings clearly
  • Version types carefully

​
Model Development

  • Use semantic types for fields
  • Keep models service-specific
  • Don’t share models between services

​
Service Integration

  • Publish service contracts to TaxiQL server
  • Use semantic types in operation signatures
  • Let TaxiQL handle data mapping

​
Measuring Success

Your implementation is successful when:

  • Services can evolve independently
  • Data integration requires minimal code
  • New consumers can easily discover and use data
  • Changes to one service don’t cascade to others
  • Semantic meaning is preserved across systems
Previous
Java / Kotlin
Next
Best practices for taxonomy development