Why we generate the data access layer
Inside redfly, the code that talks to the database and to Redis is generated from the schema. Here is why we chose that over writing it by hand.
Every application has a layer of code whose only job is to move rows between the database and the rest of the program. Load a row by its key. Save a changed one. Fetch a page of rows that match a filter. It is dull code, there is a great deal of it, and in most codebases it is written by hand, one table at a time.
Inside redfly we do not write that layer by hand. We generate it from the database schema (the list of tables, columns, keys and types that the database already knows about). The generated code covers both halves of the job: talking to the database, and talking to Redis, the memory cache that serves reads.
What the generator reads and what it writes
The input is the schema of the customer's database. From it we produce a typed client for each table (code that knows in advance what fields each row has): the entry points the redfly API exposes, which are Get, Insert, Update, Delete, GetRows and GetTotalRowCount. Each entry point knows the shape of its rows, the key that identifies them, and which fields can be filtered or joined on.
The same schema also drives the cache side. The generator decides how a row is stored in Redis, how a joined result or a multi-field lookup is served from Redis rather than from the database, and which cached entries must be refreshed when a given table changes. That last part is the one most teams get wrong by hand, and it is the reason we wanted a machine to do it.
Consistency is the first win
Hand-written data access drifts. One engineer caches a lookup, another does not. One remembers to refresh the cache after a write, another forgets, and the bug surfaces weeks later as a stale screen nobody can reproduce. The rules for the orders table end up subtly different from the rules for the shipments table, not because the data differs but because different people wrote them on different days.
Generated code cannot drift in that way. Every table gets the same treatment because the same generator produced it. When we fix a mistake in how a cache entry is refreshed, we fix it in the generator once, regenerate, and every table picks up the fix. There is no hunt through the codebase for the other twelve places the same pattern was copied.
The cache is correct because the generator makes it correct, not because someone remembered.
Testable once, not once per table
A hand-written data layer needs tests for every table, and in practice most tables get none. A generated layer inverts that. We test the generator against a small set of representative schemas: a table with a simple key, a table with a key made of several columns, tables joined through a shared column. If the generator produces correct code for those shapes, it produces correct code for the customer's three hundred tables that share those shapes.
We also test the generated output directly, running the same suite of reads and writes through the generated client against a real database and a real Redis, and checking that what comes back from the cache matches what the database holds. The open-source part of redfly includes the performance test program we use to compare cache hit rate and latency with conventional techniques, so the method is open to inspection.
Cheap to change when a table changes
Schemas move. A column is added, a type widens, a table is split in two. With hand-written code, each of those is a ticket: find every place the table is touched, change it, review it, test it, and hope nothing was missed. With a generator, the change is to re-read the schema and regenerate. The diff shows exactly what moved, and the tests run against the new output the same way they ran against the old.
This is why we can include schema changes in the subscription rather than treat them as billable project work. It is not because schema changes are trivial; it is because the cost of one is bounded by the generator, not by the size of the codebase.
About the 4,000x number
We say redfly is 4,000 times faster than the do-it-yourself alternative, and we want to be plain about what that compares. The figure is measured against hand-written data access and caching code produced by a team of developers, not against the raw database. A read served from Redis is faster than one served from disk, but that is not the comparison being made. The gap between a generated, cache-aware data layer and a typical hand-rolled one, with its extra round trips, its cache misses and its over-fetching (reading more than the screen needs), is where the number comes from.
We make this distinction because the number is easy to misread, and we would rather it be understood than merely impressive.
The trade we are making
Generating the data layer means giving up some hand-tuning. An engineer cannot write a bespoke query for one heavily used read and cache it in a special way, because the generator owns that path. In exchange, the whole layer behaves the same way, is tested the same way, and changes at the same cost regardless of how many tables the database has grown to. For the systems we build and run, that trade has been worth it every time.
A team using redfly gets that generated layer behind the API and never sees it; their code calls Get or GetRows, and keeping the rest correct is our job.