Skip to content

JSON Schema Description

📐 Basic Structure

The JSON schema consists of several sections:

  1. table_name - the name of the DynamoDB table
  2. hash_key / range_key - the table's primary keys
  3. attributes - key attributes used in indexes
  4. common_attributes - regular data fields
  5. secondary_indexes - secondary indexes (GSI/LSI)

🧾 Examples

json
{
  "table_name": "users",
  "hash_key": "user_id",
  "attributes": [
    {"name": "user_id", "type": "S"}
  ],
  "common_attributes": [
    {"name": "email",     "type": "S"},
    {"name": "age",       "type": "N"},
    {"name": "is_active", "type": "BOOL"}
  ]
}
json
{
  "table_name": "user_posts",
  "hash_key": "user_id",
  "range_key": "created_at",
  "attributes": [
    {"name": "user_id",    "type": "S"},
    {"name": "created_at", "type": "S"},
    {"name": "status",     "type": "S"},
    {"name": "category",   "type": "S"},
    {"name": "priority",   "type": "N"}
  ],
  "common_attributes": [
    {"name": "title",      "type": "S"},
    {"name": "content",    "type": "S"},
    {"name": "tags",       "type": "SS"},
    {"name": "view_count", "type": "N"}
  ],
  "secondary_indexes": [
    {
      "name": "lsi_by_status",
      "type": "LSI",
      "range_key": "status",
      "projection_type": "KEYS_ONLY"
    },
    {
      "name": "gsi_by_category",
      "type": "GSI",
      "hash_key": "category",
      "range_key": "created_at",
      "projection_type": "ALL"
    },
    {
      "name": "gsi_by_status_priority",
      "type": "GSI",
      "hash_key": "status",
      "range_key": "priority",
      "projection_type": "INCLUDE",
      "non_key_attributes": ["title", "view_count"]
    }
  ]
}
json
{
  "table_name": "analytics_metrics",
  "hash_key": "user_id", 
  "range_key": "event_timestamp",
  "attributes": [
    {
      "name": "user_id",
      "type": "S"
    },
    {
      "name": "event_timestamp", 
      "type": "N",
      "subtype": "int64"
    }
  ],
  "common_attributes": [
    {
      "name": "session_count",
      "type": "N", 
      "subtype": "int32"
    },
    {
      "name": "conversion_rate",
      "type": "N",
      "subtype": "float32" 
    },
    {
      "name": "total_revenue_cents",
      "type": "N",
      "subtype": "uint64"
    },
    {
      "name": "priority_level",
      "type": "N",
      "subtype": "int16"
    },
    {
      "name": "test_scores",
      "type": "NS",
      "subtype": "int32"
    },
    {
      "name": "conversion_rates_history", 
      "type": "NS",
      "subtype": "float32"
    },
    {
      "name": "transaction_amounts",
      "type": "NS", 
      "subtype": "uint64"
    },
    {
      "name": "rating_values",
      "type": "NS",
      "subtype": "int16"
    },
    {
      "name": "daily_timestamps",
      "type": "NS",
      "subtype": "int64"
    }
  ],
  "secondary_indexes": []
}
json
{
  "table_name": "multi_tenant_posts",
  "hash_key": "tenant_id",
  "range_key": "post_created_at",
  "attributes": [
    {
      "name": "tenant_id", 
      "type": "S"
    },
    {
      "name": "post_created_at",
      "type": "S"
    },
    {
      "name": "user_id",
      "type": "S" 
    },
    {
      "name": "category",
      "type": "S"
    },
    {
      "name": "post_type",
      "type": "S"
    },
    {
      "name": "status",
      "type": "S"
    },
    {
      "name": "priority",
      "type": "N"
    }
  ],
  "common_attributes": [
    {
      "name": "title",
      "type": "S"
    },
    {
      "name": "content", 
      "type": "S"
    },
    {
      "name": "tags",
      "type": "SS"
    },
    {
      "name": "view_count",
      "type": "N"
    }
  ],
  "secondary_indexes": [
    {
      "name": "gsi_user_posts",
      "type": "GSI",
      "hash_key": "TENANT#tenant_id#user_id",
      "range_key": "post_created_at", 
      "projection_type": "ALL"
    },
    {
      "name": "gsi_category_posts",
      "type": "GSI", 
      "hash_key": "BLOG#tenant_id#category",
      "range_key": "post_created_at",
      "projection_type": "KEYS_ONLY"
    },
    {
      "name": "gsi_status_priority",
      "type": "GSI",
      "hash_key": "status#tenant_id", 
      "range_key": "META#post_type#priority",
      "projection_type": "INCLUDE",
      "non_key_attributes": ["title", "view_count"]
    },
    {
      "name": "lsi_by_user",
      "type": "LSI",
      "range_key": "USER#user_id#post_type",
      "projection_type": "ALL"
    }
  ]
}

🔒 Required Fields

table_name

Type: string
Example: "user_profiles"

Logical name of the DynamoDB table.

Used to generate:

  • Go package name (in lowercase)
  • File name (table_name.go)
  • TableName constant in code

WARNING

Package will be userprofiles, file will be userprofiles.go


hash_key

Type: string
Example: "user_id"

The partition key (hash key) of the DynamoDB table.

Must reference one of the attributes from the attributes array.


attributes

Type: array of objects
Example: {"name": "user_id", "type": "S"}

Array of key attributes.

Used in primary keys and indexes.

Consists of:

  • name

    Type: string
    Example: "user_id"

    Attribute name.

    Must be unique across all table attributes.

  • type

    Type: string
    Example: "S"

    DynamoDB data type

    DynamoDB TypeGo TypeDescription
    "S"stringString
    "N"int64Number
    "BOOL"boolBoolean
    "SS"[]stringString Set
    "NS"[]intNumber Set
    "string"stringAlias for "S"
    "number"int64Alias for "N"
    "boolean"boolAlias for "BOOL"
  • subtype

    Type: string (optional)
    Example: "uint64"

    Specifies Go type.

    Only applicable for "N" and "NS" types.

    DynamoDB TypeSubtypeGo TypeDescription
    "N""int32"int3232-bit integer
    "N""int64"int6464-bit integer (default)
    "N""float32"float3232-bit float
    "N""uint64"uint6464-bit unsigned integer
    "N""int16"int1616-bit integer
    "NS""int32"[]int32Set of 32-bit integers
    "NS""int64"[]int64Set of 64-bit integers
    "NS""float32"[]float32Set of floating-point numbers
    "NS""uint64"[]uint64Set of unsigned integers
    "NS""int16"[]int16Set of 16-bit integers

🔓 Optional Fields

range_key

Type: string
Example: "timestamp"

Sort key (range key) of the DynamoDB table.

If specified, it must reference one of the attributes from the attributes array.


common_attributes

Type: array of objects
Example: {"name": "email", "type": "S"}

Array of regular data attributes.

These attributes CANNOT be used in index keys — only for storing information.

The object structure is the same as in attributes.


secondary_indexes

Type: array of objects

Array of secondary indexes (GSI and LSI) for advanced query capabilities.

Consists of:

  • name

    Type: string
    Example: "user_id"

    Index name.

    Must be unique within the table.

  • type

    Type: string
    Example: "GSI"

    Index type:

    • GSI (Global Secondary Index) — can use any hash_key
    • LSI (Local Secondary Index) — uses the table's main hash_key
  • hash_key

    Type: string
    Required: Yes for GSI, optional for LSI

    Hash key for the index.

    Must reference an attribute from attributes and be different from the table's range_key (for LSI).

  • projection_type

    Type: string
    Values: "ALL", "KEYS_ONLY", "INCLUDE"

    Specifies which attributes are projected into the index:

    • ALL — all attributes from the base table
    • KEYS_ONLY — only index and table keys
    • INCLUDE — keys + additional non_key_attributes
  • non_key_attributes

    Type: array of strings
    Required: Only when projection_type = "INCLUDE"

    List of additional attributes to include in the index.

  • read_capacity and write_capacity

    Type: integer
    Required: No

    Provisioned throughput settings for GSI.

    LSIs use the base table's capacity settings.

    Applies only to: GSI

🔑 Composite Keys

json
{
  "name": "user_status_index",
  "type": "GSI",
  "hash_key": "user_id#status",
  "range_key": "created_at"
}

Composite key user_id#status creates a key by combining the user_id and status attributes.

🛡️ Validation

GoDyno automatically checks:

  • All keys reference existing attributes
  • Index names are unique
  • Projection types are valid
  • non_key_attributes are only used with the INCLUDE projection
  • LSI must have a range_key
  • GSI must have a hash_key
  • LSI range_key must differ from the table's range_key

If validation errors are found, code generation will fail with a detailed problem description.

Released under the MIT License.