Schema Design

A FLXBL schema defines your data model with entities (like tables) and relationships (graph edges connecting entities).

Visual Schema Editor

The easiest way to design your schema is using the visual Schema Editor in your FLXBL dashboard. Create entities, define fields with dropdown type selectors, and draw relationships by dragging between entity nodes.

FLXBL Entity Editor Panel showing field types and configuration
Entity Editor Panel with fields, types, and required toggles

The Schema Editor automatically handles versioning and shows a breaking changes dialog when you modify existing fields.

Entities

An entity represents a type of data in your application. Each entity has a name and a list of fields with types.

{
  "name": "Product",
  "description": "Products available in the store",
  "fields": [
    { 
      "name": "name", 
      "type": "STRING", 
      "required": true,
      "description": "Product display name"
    },
    { 
      "name": "description", 
      "type": "TEXT", 
      "required": false,
      "description": "Detailed product description"
    },
    { 
      "name": "price", 
      "type": "FLOAT", 
      "required": true 
    },
    { 
      "name": "quantity", 
      "type": "NUMBER", 
      "required": true 
    },
    { 
      "name": "isActive", 
      "type": "BOOLEAN", 
      "required": false 
    },
    { 
      "name": "publishedAt", 
      "type": "DATETIME", 
      "required": false 
    },
    { 
      "name": "metadata", 
      "type": "JSON", 
      "required": false 
    },
    { 
      "name": "status", 
      "type": "ENUM", 
      "required": true,
      "enumValues": ["draft", "published", "archived"]
    },
    { 
      "name": "tags", 
      "type": "STRING_ARRAY", 
      "required": false 
    }
  ]
}

Field Types

FLXBL supports the following field types:

Type Description Example Values
STRING Short text (up to 255 chars) "Hello World"
TEXT Long text (unlimited) Article body, descriptions
NUMBER Integer 42, -10, 0
FLOAT Decimal number 3.14, 99.99
BOOLEAN True/false true, false
DATETIME ISO 8601 timestamp "2025-01-15T10:30:00Z"
JSON Arbitrary JSON object {"key": "value"}
ENUM Predefined values "draft", "published"
PASSWORD Securely hashed password Automatically hashed on write
STRING_ARRAY Array of strings ["tag1", "tag2"]
NUMBER_ARRAY Array of integers [1, 2, 3]
FLOAT_ARRAY Array of decimals [1.5, 2.5, 3.5]
BOOLEAN_ARRAY Array of booleans [true, false, true]

Field Options

  • name (required) - Field identifier, must be unique within entity
  • type (required) - One of the supported field types
  • required (required) - Whether the field must have a value
  • description (optional) - Human-readable description
  • enumValues (required for ENUM) - Array of allowed values

Identity Entities

Any entity can become an identity entity by adding two properties. This enables end-user authentication (registration, login, password reset) for your application's users.

{
  "name": "Customer",
  "isIdentity": true,           // Enables auth endpoints
  "identifierField": "email",   // Field used for login
  "fields": [
    { "name": "email", "type": "STRING", "required": true },
    { "name": "password", "type": "PASSWORD", "required": true },
    { "name": "name", "type": "STRING", "required": false },
    { "name": "role", "type": "STRING", "required": false }
  ]
}

When an entity is marked as identity:

  • Auth endpoints are enabled/register, /login, /reset-password, etc.
  • The entity remains accessible via Dynamic API — For admin operations like listing users
  • PASSWORD fields are automatically hashed and redacted — Secure by default

Requirements

Property Description
isIdentity: true Marks this entity as the identity provider for your tenant
identifierField The STRING field used for login (typically email)
PASSWORD field At least one field with type PASSWORD

Learn more in End-User Authentication.

Relationships

Relationships define how entities connect to each other. FLXBL stores these as graph edges in Neo4j, enabling powerful traversal queries.

{
  "relationships": [
    {
      "name": "BELONGS_TO",
      "sourceEntityName": "Product",
      "targetEntityName": "Category",
      "cardinality": "MANY_TO_ONE",
      "description": "Products belong to one category"
    },
    {
      "name": "PURCHASED_BY",
      "sourceEntityName": "Product",
      "targetEntityName": "Customer",
      "cardinality": "MANY_TO_MANY",
      "fields": [
        { "name": "quantity", "type": "NUMBER", "required": true },
        { "name": "purchasedAt", "type": "DATETIME", "required": true },
        { "name": "unitPrice", "type": "FLOAT", "required": true }
      ]
    },
    {
      "name": "REVIEWED_BY",
      "sourceEntityName": "Product",
      "targetEntityName": "Customer",
      "cardinality": "ONE_TO_MANY",
      "fields": [
        { "name": "rating", "type": "NUMBER", "required": true },
        { "name": "comment", "type": "TEXT", "required": false }
      ]
    }
  ]
}

Cardinality Types

Cardinality Description Example
ONE_TO_ONE Each source links to exactly one target User → Profile
ONE_TO_MANY Each source links to multiple targets Author → Posts
MANY_TO_ONE Multiple sources link to one target Products → Category
MANY_TO_MANY Multiple sources link to multiple targets Products ↔ Tags

Relationship Properties

Relationships can have their own fields (properties on the edge). This is useful for storing metadata about the connection:

  • PURCHASED_BY: quantity, purchasedAt, unitPrice
  • REVIEWED_BY: rating, comment, createdAt
  • FOLLOWS: followedAt, notificationsEnabled

Complete Schema Example

Here's a complete schema for an e-commerce application:

{
  "entities": [
    {
      "name": "Product",
      "fields": [
        { "name": "name", "type": "STRING", "required": true },
        { "name": "price", "type": "FLOAT", "required": true },
        { "name": "tags", "type": "STRING_ARRAY", "required": false }
      ]
    },
    {
      "name": "Category",
      "fields": [
        { "name": "name", "type": "STRING", "required": true },
        { "name": "slug", "type": "STRING", "required": true }
      ]
    },
    {
      "name": "Customer",
      "fields": [
        { "name": "email", "type": "STRING", "required": true },
        { "name": "name", "type": "STRING", "required": true }
      ]
    }
  ],
  "relationships": [
    {
      "name": "BELONGS_TO",
      "sourceEntityName": "Product",
      "targetEntityName": "Category",
      "cardinality": "MANY_TO_ONE"
    },
    {
      "name": "PURCHASED_BY",
      "sourceEntityName": "Product",
      "targetEntityName": "Customer",
      "cardinality": "MANY_TO_MANY",
      "fields": [
        { "name": "quantity", "type": "NUMBER", "required": true }
      ]
    }
  ],
  "description": "E-commerce schema with products, categories, and customers"
}

Schema Validation

Before publishing, you should validate your schema to catch errors:

// Ask your AI assistant:
"Validate my schema before publishing it"

// Or use the MCP tool directly:
validate_schema({
  entities: [...],
  relationships: [...]
})

The validator checks for:

  • Reserved entity names (id, createdAt, updatedAt)
  • Invalid field types
  • Missing required properties
  • Duplicate entity or field names
  • Invalid relationship references
  • Breaking changes from previous versions

Best Practices

  • Use descriptive names: Entity and field names should be self-documenting
  • Add descriptions: Help future developers understand your schema
  • Start simple: Begin with core entities and add complexity later
  • Use relationships: Graph relationships are more flexible than embedding
  • Consider queries: Design your schema based on how you'll query data

Next Steps