Skip to content
Home
Blog
Notes
Back to Blog

Type-safe Drizzle selects from Zod page schemas

October 11, 2026•3 min read

Derive a Drizzle select from a Zod page schema so Aurora returns only the columns a screen needs, and TypeScript fails when the table, the schema, and the view drift apart.

Cover image for Type-safe Drizzle selects from Zod page schemas
drizzleaurora data api

Table of Contents

  • Introduction
  • Drizzle schema
  • The frontend
  • Add a field
  • Remove a column
  • Conclusion
  • Sources and References

Introduction

Aurora Data API responses are size-limited, so a Drizzle query should select only the columns a screen uses. In the Aurora persons example, a Zod page schema is that list. pageColumns reads the schema keys and builds the Drizzle selection. readAuroraPersonList selects those columns and nothing else. getAuroraPersonList then parses each row with the list view, which is the type the table renders.

The running app is the Aurora persons demo. The source is the tanstack-aws repository.

Paging is another way to stay inside the response limit. It is left out here.

Drizzle schema

createSelectSchema(persons) mirrors the Drizzle table. personListSchema picks the columns the list is allowed to read: id, firstName, lastName, and gender. dateOfBirth already exists on the persons table and on personDetailSchema. The list does not select it yet.

person list schema after adding date of birth

personListColumns is pageColumns(persons, personListSchema). The list read uses that object as the select argument.

Drizzle column selection from the page schema

The frontend

The persons screen has a list and a detail view. List columns come from AuroraPersonListRow, the output of auroraPersonListView. In table.tsx, id is the row link, and every other list field needs a column. A key that is not on the row fails at the accessor. A row field with no column fails satisfies Record<ListColumnKey, unknown>.

The published view maps each picked column straight through. Nullable values go through absent, which turns null into undefined. satisfies ViewOf<typeof personListSchema> rejects a view that drops or invents a key.

Add a field

The list should show dateOfBirth, but only the year. Adding birthdayYear to the table fails until the view returns that key.

add birthday year column

The stored timestamp has to be on personListSchema first, so pageColumns can select it. The list still does not render the full date.

add date of birth to the list schema

The published auroraPersonListView copies each picked field through. Replace that with a transform: dateOfBirth becomes birthdayYear, and everyColumnRead fails the build when a picked column is left unread. The detail view beside it already returns the full timestamp.

transform date of birth into birthday year

The list shows the year. The query still selects only the page-schema columns.

list with birth year

Remove a column

Removing gender follows the same chain. Commenting it out in columnsByField is not enough: the row type still includes gender until the view stops returning it.

remove the gender column

Stop returning it from the list view. everyColumnRead(rest) stays red while gender: true is still on the page schema, because gender is still in rest.

list view while gender is still picked

Then take it off the list pick. rest is empty, and the select no longer asks Aurora for gender. The detail schema can keep it.

remove gender from the list schema

The list no longer shows gender, and the query no longer selects it.

list without gender

Conclusion

The page schema is the contract. The table must cover every view field, the view must read every schema field, and the Drizzle select is derived from that schema. Adding or removing a list field fails the build until person-schema.ts, view.ts, and table.tsx stay in sync, which keeps the Aurora query limited to the columns the screen needs.

Sources and References

  • Aurora persons demo
  • tanstack-aws
  • personListSchema
  • pageColumns and readAuroraPersonList
  • auroraPersonListView
  • columnsByField
  • getAuroraPersonList

Published on October 11, 2026

Share:Bluesky Icon
Categories: aws

Related Posts

Oct 12, 2026

Feature-stack databases and Drizzle migrations on shared Aurora

Mar 28, 2026

Aurora PostgreSQL Serverless (Express configuration) with CDK and Drizzle

Apr 23, 2026

CDK Mixin for setting recommended TLS version for API Gateway and endpoint access mode

RSS|

© 2026 Johannes Konings. All rights reserved.