Перейти до вмісту

The Dictionary Before You Map

Цей контент ще не доступний вашою мовою.

Module 4 in the chapter Understanding Your Data Structures, chapter 3 of the Data 360 Architect course. Each module stands on its own. Previous: What Makes It Unique · Next: Don’t Bring In Everything

The question this module answers: What goes in a data dictionary for a Data 360 source, and why build it before the first stream?

I’ve done entire Service Cloud implementations where I don’t even touch Salesforce. Every field, every picklist, the assignment rules, the escalation rules, the milestones: I map everything in a spreadsheet, get it all dialed in, and then plug it into the org. It catches things. And as I got into Data 360, I found it almost requires that you do this mapping ahead of time.

A data dictionary is a list of every field in your data, one row per field, that says what the field means, what type of value it holds, which values are allowed, where it comes from and where it goes. It’s written for people: the architect, the admin who builds the stream, the analyst who builds the segment, and whoever has to fix it in two years. If someone asks “what does closed mean in the runways file, and what values can it have?”, the dictionary answers in one row.

The Data Architect course covers the data dictionary as a record of what data means: definitions, sources and owners. Here I use it for something else: as the place where the design happens, before anything is built.

The idea is simple. A shared spreadsheet, one row per field. For each field, you write down what it means, what type it is, where it’s going and why you need it. You don’t open Data 360 until the sheet is right.

And I keep one habit on every project. When someone adds a field to the design, it gets flagged yellow. It stays yellow until it actually exists: built in the dev org and in source control. Then the color clears. At any moment, the yellow rows are the difference between the design and what’s built. You catch the deltas very quickly.

That sheet has saved me more than once. It has caught wrong data types, missing keys, and keys missing their source prefix (chapter 3, module 3), all before anything was built. In Salesforce core, a dictionary like this is a lifesaver. In Data 360 it matters even more, because everything is so concrete. Find a problem in a data model object, and you may have to go all the way back to the stream, with every mapping on the way dropped and recreated. So you need to see these things ahead of time.

First, every feed: its structure and a sample

Section titled “First, every feed: its structure and a sample”

Before the first row of the dictionary, list every feed that will come in: every file, every API, every org. Then get two things for each one from whoever produces it.

  • Its structure. The layout of the file, the schema of the API, the fields of the object: whatever says what’s supposed to be in it.
  • A sample of real data. Not a made-up example. Real rows, enough of them to see the variety: the blanks, the odd spellings, the values nobody mentioned.

Then lay the sample against the structure. Is every field in the structure actually in the sample? Is there anything in the sample the structure doesn’t mention? Does a field called a date hold dates, all in one format? Does the field that’s supposed to be unique repeat? The structure tells you what the producer meant. The sample tells you what you’re really getting. Where they disagree, ask before you design, not after the first load.

Then, for each feed, answer a few questions once, at the top of its part of the dictionary:

QuestionThe pilots fileThe flights
Who produces it?An outside pilot records system, as a file in Amazon S3US airlines report every flight to the Bureau of Transportation Statistics (BTS), which publishes them by month
Where’s the structure?The file’s header row and the producer’s note (SkyData’s card)BTS’s column guide, and SkyData’s card
Do we have a real sample?Yes, the whole file: 1,000 pilotsYes, a whole month: 29,524 flights at PHX, August 2026
How often does it come?Once a dayOnce a month, after the month is over
Every record each time, or only changes?Every pilot, every timeA new month’s flights each time
How is a row uniquely identified?pilot_idFour values together: date, airline, flight number, origin (module 3)
Is it a time series: one row for each thing that happens, at a point in time?NoYes
If it’s a time series, which date never changes?None: airlines reschedule flights, sometimes weeks ahead (so flights are other data, chapter 6)

A feed sheet for this course’s two sources. Both files are on SkyData (opens in a new tab): the pilots are synthetic, the flights are real.

Most of these answers have a module of their own: the key in module 3, every record or only changes in chapter 4. The last one needs a closer look.

If a feed is a time series, one row for each event, then one of its dates has a special job. In Data 360, a time series of what people do comes in as engagement data, and an engagement stream needs an event time field: the date that says when the event happened (chapter 6, module 3). That date has to be immutable: once the record exists, it never changes.

Salesforce is direct about why: “Using a mutable date field causes duplication of records where multiple records with the same primary key get added to the data lake object (DLO).” And you can’t fix it later: “The Event Time Field isn’t editable after initial setup.”

So in the dictionary, every date field gets one more answer: does it change after the record is written? Here are the flight’s dates and times:

FieldWhat it holdsChanges after the record is written?Can it be the event time?
FlightDateThe day of the flight, 2026-08-14Yes, if the flight is moved to another dayNo
CRSDepTimeScheduled departure, local time, hhmmYes: airlines reschedule, sometimes more than once, weeks aheadNo
DepTimeActual departure, local time, hhmmYes, in a live feed: blank until the plane leavesNo
ArrTimeActual arrival, local time, hhmmYes, in a live feed: blank until it landsNo

From BTS’s August 2026 flights on SkyData.

One more thing the file teaches. BTS’s own record layout says FlightDate is written yyyymmdd. The file says 2026-08-02. Same lesson as the airport types in chapter 7: check the data, not only the documentation, and write down what you actually found.

BTS publishes a month only after it’s over, so nothing in this file changes any more. But design for the feed, not the file. In a live feed, the actual times fill in as the day goes on and change while a flight is delayed, and even the schedule moves: airlines reschedule flights, sometimes two or three times, weeks or months ahead. No flight date holds still. That decides the category in chapter 6: in this course, flights are other data, and their dates are ordinary fields.

And look at what the scheduled time is missing. It’s local time, written hhmm, with no time zone. (And in the actual times, BTS writes midnight as 2400, never 0000: chapter 6.) Salesforce’s rule for dates and times (below) means you can’t send it as it is. You build a proper date and time from three things: the date, the scheduled time, and the origin airport’s time zone. PHX is easy: Arizona stays on UTC−7 all year. Most US airports change for daylight saving time. That’s a field you make, so every departure can be read in one time, and it gets a row of its own (below).

The pilots file isn’t a time series, and it has no date at all. That’s a gap worth writing down: with no “last changed” date, a daily file can’t tell you which pilots changed today. Ask the producer for one now, while it’s a question in a spreadsheet.

And if a time series has no date that never changes? Salesforce’s tip: “If you have a time-series dataset and you don’t have an immutable date field, choose the Other category.” That’s our flights. For a source about people’s activity, ask the producer for one.

For a source on its way into Data 360, the dictionary needs a few columns a core org project doesn’t. Here’s the pilots file from chapter 1:

Source fieldWhat it meansData 360 typeKeySensitive?Lands in (DLO field)Maps to (DMO field)Used for
pilot_idThe pilot, as the file’s owner identifies them, PLT-000238TextPrimaryNopilot_idIndividual IDEvery load, every delete
first_name, last_nameThe pilot’s nameTextYesfirst_name, last_nameIndividual: first and last nameMatching, display
emailEmailEmailMatchYesemailContact Point EmailIdentity resolution
phonePhone, +15205550138PhoneMatchYesphoneContact Point PhoneIdentity resolution
home_airportThe home airport’s IATA code, PHXTextForeign, to the airportNohome_airport(stays on the lake for now)Which airport’s Account the contact belongs to
flying_roleWhat kind of flying, Airline pilotTextNoflying_roleIndividual: flying role (custom)The enrichment
highest_certificateThe highest pilot certificate heldTextNohighest_certificate(stays on the lake for now)Segments, later
years_flyingWhole yearsNumberNoyears_flyingIndividual: years flying (custom)The segment; the enrichment
record_sourceSays the row is synthetic, and which generator made itTextNorecord_source(stays on the lake)Tracing

A dictionary for SkyData’s pilots file (synthetic). The custom fields on the Individual are this course’s example.

Every column is a decision from this chapter. The type comes from module 1. The key column comes from module 3. Sensitive? is module 5. Lands in and Maps to are the mapping you’ll build in chapters 6 and 8, decided here first. And Used for is the question that keeps fields out: if nobody can fill it in, the field doesn’t come in.

Here’s one for a file somebody else made, with no generator to tidy it: the OurAirports runways file from modules 2 and 3, 48,412 runways and 20 columns in SkyData’s v1.0. I’ve added two columns this time: Values, what’s actually in the field, and Decision.

Source fieldWhat it meansValues in the fileData 360 typeKeyDecisionUsed for
idThe runway’s own ID234792TextPrimaryBring inEvery load, every delete
airport_refThe airport’s ID1990TextForeign, to the airportBring inThe relationship to the airport
airport_identThe airport’s codeCYYZTextBring inDisplay and search
length_ftLength in feet11120NumberBring inSegments: airports with a runway over 10,000 ft
width_ftWidth in feet200NumberBring inNot yet known
surfaceWhat the runway is made of667 different values, and blanks (see below)TextBring in, clean in a transformSegments by surface
lightedLit for night use1 or 0Boolean? (see below)Bring inSegments: lit runways
closedClosed1 or 0Boolean? (see below)Bring inLeave closed runways out
le_ident, he_identThe two ends’ names05 and 23TextBring inDisplay
le_ and he_ latitude, longitude, elevation, heading, displaced thresholdWhere each end is, and how it’s laid out43.67, -79.66, 564, 47, 135NumberLeave outNothing yet

A dictionary for the OurAirports runways file (public domain), for this course. “Used for” is this course’s example.

Filling in the Values column means opening the file and looking, and that’s where the real file starts talking.

The surface column has 667 different values. Asphalt alone is ASP on 11,396 runways, ASPH on 1,681, Asphalt on 272 and asphalt on 133. Turf is TURF, Turf and turf. Concrete is CON, CONC and concrete. 510 runways have no surface at all. Nothing in Data 360 will complain: they’re all valid text. But a segment of “asphalt runways” built on ASP misses more than 2,000 of them. The dictionary is where you notice, and where you decide: a transform that maps each spelling to one value (chapter 7), and a list of the allowed values written in the row.

lighted and closed say 1 and 0. That looks like a yes or no, so Boolean is the natural type. But Salesforce Help says a Boolean’s “Possible values are ‘true’, ‘false’, and blank.” A 1 isn’t one of them. So it’s a decision, made here, not discovered after the load: test a sample to see what a 1 becomes, bring the field in as a number, or turn it into true or false on the way in. Help also says a Boolean can’t be a primary key or a record modified field, which doesn’t matter here, but would for a different field.

Ten fields stay out. The two ends’ positions, elevations and headings are good data, and nobody has a use for them yet. Bringing them in is easy, but every field that comes in is one more field to type, map, explain and keep. They stay in the file, and in the dictionary, marked “Leave out.” The day someone needs them, the row is already written.

Some fields in your dictionary won’t come from the source at all. For the flights, a few are made on the way in:

FieldWhere it comes from
Flight_KeyMade: four values joined into one key, 2026-08-14_AA_336_DFW (module 3)
sched_dep_atMade: FlightDate plus CRSDepTime, in the origin airport’s time zone, so departures can be compared in one time. A field, not an event time (chapter 6)
source_file_nameMade: which month’s file the row came from (see below)

This course’s design for BTS’s flights on SkyData. BTS already supplies the delays (DepDelay, ArrDelay) and their causes, so we don’t work them out.

So add one more column: Comes from. “The source” for most rows; for the rest, how it’s made. A field that’s worked out needs its rule written down, because six months later, the scheduled departure time will be in a dashboard, someone will ask what time zone it’s in and what happened to the flights at 2400, and the answer has to be in one place. And where it’s made is a design decision too: before it’s sent, as here, or in Data 360 with a formula field or a transform (chapters 6 and 7).

Six months in, someone finds a strange value on one record and asks: which file did it come from? Data 360 adds a few fields of its own to every lake object (chapter 6, module 5), and one of them, Data Source Object, names “the object where the record came from, such as the name of a cloud storage file.” For a stream that reads one fixed file, that answers it. When one stream picks up a new file every day, it may not say which day’s file. I haven’t tested whether it then holds each file’s own name or the stream’s pattern, and I wouldn’t design on either.

The sure way is to ask whoever makes the file to write it into every row. I put three of these in the dictionary for any file source, with “Comes from: the producer”:

FieldWhat it holdsWhy
source_file_nameThe name of the file this row was inTrace any row back to its file
batch_idOne ID for each run that made a fileFind, count or remove everything from one bad run
extracted_atWhen the producer read the record from its systemTell which version of a record is newest

SkyData’s files carry a cousin of these: record_source on every synthetic row, and a dated version on every file. These columns are for tracing, not for the key. Put the file name into the primary key and the same record sent again in a new file becomes a second row (module 3). Keep them out of the key, unless every file’s rows are meant to be kept.

When you create a data stream, Salesforce Help says, “Data 360 attempts to detect the data type of each field.” Attempts. It’s a good starting point, not a decision. In my org it read years flying as a number, which was right, and the flight number as a number too, which wasn’t: you never add flight numbers up (chapter 7). Module 1’s years flying problem is what happens when nobody decides. The dictionary is where you decide the type yourself, before the stream suggests one.

Salesforce’s own description of the types shows why it’s worth the effort:

  • Numbers: “If an ingested number is out of the supported range or is a non-numerical value, a null value is stored.” A years flying of “twelve” doesn’t fail. It becomes blank.
  • Dates and times: “A valid datetime must include the time part and time zone. If they’re not included, it’s inferred as 00:00:00 UTC.” A departure sent as a date alone, with no time and no zone, becomes midnight UTC, which in much of the world is the day before.
  • Phone and email: “Data 360 doesn’t validate the format of the phone number.” If you need clean phone numbers for matching, you clean them before they come in, or in a transform.
  • Mapping: “The data type of the DLO field must match the data type of the DMO field,” with one exception: a Number can map to Text. So the type you pick at the lake has to suit the model you’ll map it to.

None of these make a load fail. They make it quietly wrong, which is worse. A dictionary with a type column, checked against a sample of the real file, catches them while they’re still a cell in a spreadsheet.

One last habit. When I review a dictionary, or a finished mapping, I like tracing it from right back to left, so I get to trace the keys and the mappings. Start at the Used for column, then the DMO field, then back to the source. If a row can’t be traced all the way back to a real field in the real file, something is missing. If a source field has nothing on its right, ask why it’s coming in at all.

Why carry it through a whole course? Because so much of what you create in Data 360 can’t be undone. You’ve met the rules already, in Salesforce’s words. “After a DLO or DMO is created, you can’t change the data type of any fields.” A data stream’s category can’t be changed after it’s saved, and “the Event Time Field isn’t editable after initial setup.” Fields can’t be deleted from a lake object, only disabled. And the names you give streams and lake objects are the names everything downstream uses. Every one of those is a decision you make once, on the day you create the stream. The dictionary is where you make it on purpose, with the whole picture in front of you, instead of in a hurry on a setup screen. And it’s how you find out what depends on a field before you touch it.

From here on, this course builds one dictionary with you. Start it now, for the three feeds you’ve met: the pilots, the flights and the airports. Use the columns above: what each field means, its type, its key, whether it’s sensitive, and what it’s used for. A sheet is fine.

Every chapter after this adds to it. Chapter 4 adds how each feed arrives. Chapter 6 adds the category, the event time and the lake object’s fields. Chapter 7 adds the transforms, and chapter 8 the model it all maps to. Each chapter ends with a short step to update yours. SkyData publishes the dictionary as it should look at the end of each chapter, so you can check your work: start from its blank dictionary template (opens in a new tab), and compare yours with the chapter 3 edition (opens in a new tab). By the end of the course, it’s a complete map of everything you built, from each file to the model. The Data Dictionary reference page explains the method, including how a dictionary grows from a sheet into a model in Git.

In 2024 I filmed the data dictionary I use to plan a design before I set anything up in Salesforce: a shared sheet with every object and field, its type, its purpose, and whether it’s built yet. That video was about the core platform, and in it I said that Data Cloud, now Data 360, “almost requires” this kind of mapping ahead of time. This chapter, and the dictionary you’ll grow through the course, is that same habit, carried into Data 360. What’s changed is how much it covers. In 2024 it described the Salesforce objects I was going to build. In Data 360 it has to describe everything that comes in, whatever its shape: objects, flat files, pivoted tables, JSON, free text. And it’s now something AI tools can read and work from too, which is why my own moved from a sheet to YAML files in Git. The Data Dictionary reference page tells that story. The note under the video says what’s still right and what’s changed since.

STA 2.11 · Data Architecture: Using a Data Dictionary for Planning Before You Setup in Salesforce · 10:03 · published 2024-01-26 · plays from YouTube when you click it · Watch on YouTube · More videos: Salesforce Data Architecture Videos
  • Who owns the dictionary, and that nothing is built in Data 360 that isn’t in it first.
  • For every feed: its structure and a real sample, received and compared before the design starts.
  • For every feed: how a row is uniquely identified, every record or only changes, and whether it’s a time series.
  • For every time series: the date that never changes, or the decision to make it Other.
  • The type of every field, decided and checked against real sample data, not left to detection.
  • The allowed values for each coded field, and where the different spellings are cleaned.
  • For every field that’s made or worked out, its rule, and where it’s made.
  • Which columns the producer writes into every row so any record can be traced to its file and run.
  • Which fields have no use yet, and stay out until they do.

All checked 2026-11-14.