Serverless data lake layout
A data lake that keeps every file exactly as it arrived, and can rebuild everything derived from it whenever the processing changes.
By: Benjamin Clark
Intent
This pattern assumes a platform that takes in data as files, and needs a flexible way to query that data, including questions nobody planned for when it arrived. It lays out a data lake in tiers on serverless storage, one tier for each stage of the data's life, from files exactly as they were delivered to data ready for analysis. Each tier has one purpose, and its own rules about what may write to it and what may read from it. The tiers cover the bronze and silver layers of the medallion architecture, and the gold layer, which holds the business-level views people report from, sits on top of them, in a data warehouse or a query layer. This enables three outcomes:
- Every file is kept exactly as it arrived, so a faulty transform can never destroy the original.
- Any tier can be rebuilt from the one below it whenever the processing changes.
- Access, retention and cost are set per tier, so each consumer is given exactly the data it needs, and no more.
Motivation
When a platform keeps all its data together, with no tiers between files as they were delivered and data ready to query, it fails in three ways:
- Nobody can tell an untouched file from a cleaned one, because they sit side by side under the same permissions.
- A faulty transform can overwrite the only copy of a file, and the original is lost for good.
- Permissions, retention and cost can't be set per stage, so every consumer is given more access than it needs.
This pattern separates the data by how far it has been processed, keeping each tier in storage of its own, such as a separate bucket in an object store like Amazon S3. Files arrive in a landing tier, the only one anything outside the platform may write to. An untouched copy of each file is kept in a raw tier, so whatever happens further on, the original survives, and every later tier can be rebuilt from it. A processed tier holds each file converted into a format built for analysis, such as Parquet, ready to query. Because each tier is stored separately, access, retention and cost can be set for each one, and a consumer is given only the tiers it needs. A catalogue such as the AWS Glue Data Catalog describes the processed tier, so that a query engine such as Amazon Athena can read it, as in the serverless query layer, and an event-driven data pipeline moves each file from one tier to the next.
Applicability
Use this pattern when:
- Data arrives as files, from people or from other systems.
- You must keep every file exactly as it arrived.
- You need processed versions you can rebuild whenever the processing changes.
- People need to query the data flexibly, including in ways nobody planned when it arrived.
Do not use this pattern when:
- A handful of files come from one source, where folders in one storage location are enough.
- The data needs fast reads and updates, which belong in a database.
Structure
Variant A: One set of tiers
When the data has a single owner, such as an organisation's own internal data, this variant works best.
- There's one set of tiers, each stored separately, named by environment and tier, and declared with the rest of the platform's infrastructure.
- One catalogue describes the processed tier.
Variant B: One set per isolation boundary
When data comes from owners who must be kept apart, such as a SaaS platform's clients, or business units whose data mustn't mix, this variant works best. Each owner is an isolation boundary, with storage of its own.
- Each boundary has its own set of tiers, named from a reference that never changes, so renaming a client never means moving their data.
- Services work out where a boundary's tiers are stored from the verified caller's boundary, such as their record in config as data, so no request can name another boundary's storage.
- Each boundary has its own catalogue, so queries are kept apart in the same way as storage.
- A new boundary's tiers are created from its record, as in dynamic Terraform on demand, or through automatic client provisioning where the boundaries are clients.
Participants
| Participant | Role |
|---|---|
| Sender | Delivers files in whatever way suits it, such as browser uploads through presigned URLs, or transfers from other systems. |
| Landing tier | Receives files exactly as they're delivered, and is the only tier anything outside the platform may write to. |
| Raw tier | Keeps an untouched copy of every file, from which every later tier can be rebuilt. |
| Processed tier | Holds each file converted into a format built for analysis, with consistent column names, and partitioned so queries read only what they need. |
| Catalogue | Describes each type of dataset as a table over the processed tier, so a query engine can read it. |
| Platform storage | Holds what belongs to the platform rather than the data, such as job scripts, logs and query results, with one set per environment. |
Constraints and trade-offs
- Every tier is another copy. The raw tier duplicates landing, and the processed tier duplicates raw in another format, so storage grows with each tier, and older copies need expiring or moving to cheaper storage.
- The processed tier keeps each source's own structure, so combining data from several sources is left to the queries, or to a layer built on top.
Variant A: One set of tiers trade-offs
- The core benefit is simplicity: one set of tiers and one catalogue to run.
- The core cost is that access is set per tier rather than per owner, so it doesn't suit data that must be kept apart.
Variant B: One set per isolation boundary trade-offs
- The core benefit is isolation that holds in the storage itself, so each boundary's access, retention and cost are its own.
- The core cost is scale: storage locations multiply as boundaries times tiers, and object stores limit how many an account can hold, as S3 does with buckets, so thousands of boundaries need a quota increase, or tiers shared by prefix, with isolation that rests on policy instead.
Part of how I deliver
This is the layout I give a platform's data before anything is built on top of it, because every later decision depends on it. It's one of many patterns I bring through contract delivery, and it suits one team's data as well as a platform with thousands of clients.
Can your people trust the numbers?
I build data platforms where every file is accounted for, every original is kept, and new data can be queried as soon as it arrives. If yours is hard to trust or slow to change, book a call and we'll talk it through.
