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
    },
    {
      "name": "image",
      "type": "FILE",
      "required": false,
      "description": "Product hero image"
    },
    {
      "name": "embedding",
      "type": "VECTOR",
      "required": false,
      "vectorDimensions": 1536,
      "description": "Product description embedding for similarity search"
    }
  ]
}

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]
FILE File reference (S3-compatible storage) Presigned upload/download URLs
VECTOR Embedding vector for similarity search [0.1, 0.2, ..., 0.9] (float array)

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
  • vectorDimensions (required for VECTOR) - Number of dimensions for the embedding vector (e.g., 1536 for OpenAI, 768 for smaller models)
  • searchable (optional, STRING/TEXT only) - Enable full-text search indexing

File & Vector Fields

Two special field types enable file storage and vector similarity search:

FILE fields store references to files in S3-compatible storage. The upload workflow uses presigned URLs: request an upload URL, upload the file directly to S3, then confirm the upload. See the API Reference for the full file storage endpoints.

VECTOR fields store embedding vectors (float arrays) and enable cosine similarity search. When creating a VECTOR field, you must specify vectorDimensions to match your embedding model (e.g., 1536 for OpenAI text-embedding-3-small). Query vectors must have the same number of dimensions. See the API Reference for the vector search endpoint, or use client.vectorSearch() in the SDK.

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