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.
When the CDK app can't load your models
Sometimes it shouldn't have to: an infra bundle kept deliberately separate from the application, a synth step with none of the app's gems, models that need configuration the deploy machine doesn't have. Dump the schema where the models live, and read it where the tables are built:
# in the app, at build time — Dynamoid only
require "json"
File.write("build/tables.json", JSON.pretty_generate(Dynamoid::CDK::Schema.dump(Post)))
# in the CDK app, at synth time — aws-cdk-lib only, no Dynamoid, no app
Dynamoid::CDK::Schema.table_from(
self, "Posts", JSON.parse(File.read("build/tables.json")), removal_policy: ...
)
dump returns JSON-native data (strings, arrays, hashes, nil), and load turns it back into the same descriptor
describe would have produced. table_from accepts either.
This also makes the schema a build artifact you can diff, review or check into a deployment bundle — synthesis then depends only on what was built, not on whether the app happens to load.
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.