dynamoid-cdk-schema
Generate AWS CDK DynamoDB tables straight from your Dynamoid models.
Your Dynamoid models already declare their keys and indexes. Restating that schema by hand in your CDK stack means two
sources of truth that drift the moment you add a GSI. This gem reads a model's schema — partition and sort keys, global
and local secondary indexes, attribute types — and builds the matching TableV2, so the model is the single source of
truth for both the application and its infrastructure.
It works because the AWS CDK is a first-class Ruby library your infrastructure code can require and reflect over — the
same reason it can read your Dynamoid models. There is no separate template to keep in sync.
Installation
bundle add dynamoid-cdk-schema
aws-cdk-lib is intentionally not a dependency — it's your CDK app's, and it's referenced lazily, only when you
build a table. So the introspection half (.describe) works anywhere Dynamoid is loaded.
Usage
Inside a CDK stack (where aws-cdk-lib and your Dynamoid models are already loaded):
class MyStack < AWSCDK::Stack
def initialize(scope, id, **kwargs)
super
# Build a TableV2 from the model. Extra keyword args pass straight through to
# TableV2, so the model owns keys + indexes and you own table-level config.
posts = Dynamoid::CDK::Schema.table(self, "Posts", Post,
removal_policy: AWSCDK::RemovalPolicy::RETAIN)
# `posts` is an ordinary AWSCDK::DynamoDB::TableV2 — grant it, reference it, etc.
posts.grant_read_write_data(my_function)
end
end
That's it. If Post declares a global_secondary_index or range key, the table gets it, with the right attribute
types and projection.
Just the schema, as data
.describe needs only Dynamoid (no CDK) and returns a plain, immutable descriptor — handy for tests, tooling, or
feeding another target:
Dynamoid::CDK::Schema.describe(Post)
# => #<data Dynamoid::CDK::Schema::Descriptor
# partition_key=#<data Attribute name="id", type=:string>,
# sort_key=nil,
# global_secondary_indexes=[#<data Index name="by_recency", ...>],
# local_secondary_indexes=[]>
What it reads
- Partition and sort keys, with DynamoDB attribute types (
:string/:number/:binary) resolved the way Dynamoid resolves them. - Every global secondary index: keys, and the projection type —
ALL,KEYS_ONLY, orINCLUDE(with itsnon_key_attributes). - Local secondary indexes.
Table-level configuration Dynamoid doesn't model (billing mode, TTL, point-in-time recovery, streams, removal policy) is yours to pass through as keyword arguments — this gem is about the schema, keys and indexes.
Loading your models at synth time
cdk synth has to be able to load the model classes you pass in, so require them from your CDK app. If a model reads
application config at load time (e.g. its table name from Rails config), make that available in the synth process — the
CDK never uses the physical table name (it assigns one), so a placeholder is enough.
Development
After checking out the repo, run bin/setup to install dependencies, then bundle exec rspec to run the tests and
bundle exec rubocop to lint. bin/console gives an interactive prompt.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/omarqureshi/dynamoid-cdk-schema.
License
Available as open source under the terms of the MIT License.