Dataverse is the cloud database that powers serious Power Apps — but only if you understand how it's organized. This lesson teaches you exactly how tables, columns, and rows work together, with hands-on exercises and real business examples that build genuine competence from scratch.

Imagine your manager asks you to build a Power App that tracks customer support tickets. Users need to log new tickets, update their status, attach notes, and see a history of every interaction. You fire up Power Apps, start dragging controls onto a screen — and then hit the wall. Where does the data actually live? You need something more structured than a shared Excel file and more powerful than a SharePoint list. That's exactly the problem Microsoft Dataverse was built to solve.
Dataverse is the cloud database that sits at the heart of the Microsoft Power Platform. It stores your app's data in a structured, secure, and scalable way — and once you understand how it's organized, everything else in Power Apps (forms, views, business rules, security) starts to make sense. If you've ever used a relational database before, some of this will feel familiar. If you haven't, don't worry — we'll build the mental model from scratch, using real examples the whole way through.
By the end of this lesson, you'll be able to create tables in Dataverse, define meaningful columns with appropriate data types, understand how rows (records) get stored and retrieved, and explain why Dataverse is the right foundation for serious Power Apps projects.
What you'll learn:
This lesson assumes you have access to a Power Apps environment (a free developer plan works fine), a basic familiarity with what Power Apps is, and a general idea of what a database is — even if you've only ever seen one in Excel. You do not need SQL experience or any programming background.
Note
If you're brand new to Power Apps entirely and want to orient yourself before diving into the data layer, check out Your First Power App: Build a Data Entry Form in 30 Minutes first. It gives you just enough context to make this lesson click faster.
Let's cut through the marketing language. Dataverse is a managed relational database service hosted in Microsoft's cloud. When you store data in Dataverse, Microsoft handles the infrastructure — backups, scaling, uptime, patching — so you don't have to think about servers. You interact with your data through the Power Apps maker portal, through model-driven apps, or through canvas apps using the Dataverse connector.
The key word in "relational database" is relational. Your data isn't stored in one giant spreadsheet. Instead, it's organized into separate tables, each focused on a specific type of thing — customers, tickets, products, orders — and those tables can be related to each other. A support ticket relates to a customer. An order line item relates to an order. That structure is what makes Dataverse powerful for real business applications.
Here's what sets Dataverse apart from simpler options like SharePoint lists or Excel:
Key insight
Dataverse isn't just a place to store data — it's a platform that enforces your business rules at the data layer. That means a user filling out a form in your app, a flow updating a record in Power Automate, and an API call from an external system all play by the same rules.
Everything in Dataverse organizes itself around three fundamental concepts. Once you internalize these, the rest of the platform snaps into place.
A table in Dataverse is a structured container for one type of business entity. Think of it like a tab in a spreadsheet, except it enforces a defined structure and can contain millions of rows without breaking a sweat.
For our support ticket scenario, you might have these tables:
Each table has a name, a display name, and a schema name (a technical identifier used in formulas and integrations). When you create a table called "Support Ticket," Dataverse automatically generates a schema name like cr5a2_supportticket — the prefix is your environment's customization prefix, which keeps your custom tables from clashing with Microsoft's standard tables.
Dataverse comes with a large library of standard tables (also called system tables) — things like Account, Contact, Lead, Opportunity — that Microsoft built for common business scenarios. These are the foundation of Dynamics 365 apps, and you can use them directly or extend them. When you need something that doesn't exist, you create a custom table from scratch.
Tip
Before building a custom table for something like "Customer" or "Task," check whether a standard Dataverse table already exists for it. Using standard tables means you benefit from Microsoft's pre-built relationships, forms, and integration points — and your apps become compatible with other Power Platform solutions more easily.
There's a third type worth knowing about: virtual tables. These don't actually store data in Dataverse — they surface data from an external source (like a SQL Server database or an Azure service) and make it look like a regular Dataverse table. This is useful when you can't or don't want to migrate data into Dataverse but still want to work with it inside the platform.
A column defines one attribute of the entity your table represents. Every row in the table has a value (or an empty value) for each column. Columns are sometimes called fields in the Power Apps UI — the terms are interchangeable.
For a Support Ticket table, meaningful columns might be:
| Column Display Name | Data Type | Purpose |
|---|---|---|
| Ticket Title | Text (single line) | Brief description of the issue |
| Description | Text (multi-line) | Full details of the problem |
| Status | Choice | Current state: Open, In Progress, Resolved |
| Priority | Choice | Low, Medium, High, Critical |
| Opened Date | Date and Time | When the ticket was created |
| Resolved Date | Date and Time | When the ticket was closed |
| Customer | Lookup | Links to a row in the Customer table |
| Assigned Agent | Lookup | Links to a row in the User table |
| Resolution Hours | Whole Number | How long it took to resolve |
Each column has a data type that tells Dataverse what kind of value it should hold. This matters enormously — you can't accidentally save the word "urgent" into a date column. Dataverse enforces the type at the database level.
Here are the data types you'll use most often:
Text types:
Numeric types:
Date and time:
Choice (formerly Option Set): This is one of Dataverse's most useful types. Instead of letting users type anything they want into a "Status" field (leading to "open," "Open," "OPEN," and "opn" all meaning the same thing), you define a fixed list of allowed values. Each option has a label (what users see) and a numeric value stored internally.
Choices can be local (specific to one table's column) or global (a shared list reused across many tables). If you have a "Priority" concept that appears on tickets, tasks, and escalations, make it a global choice so the options stay consistent everywhere.
Lookup: A lookup column creates a relationship between tables. Instead of typing a customer's name into the ticket (which goes stale when the customer name changes), you store a reference to the actual Customer row. When the customer's name changes in the Customer table, every ticket automatically reflects the updated name.
Yes/No (Boolean): A simple true/false toggle. Good for "Is escalated?", "Requires follow-up?", "Customer notified?"
File and Image: Columns that store binary data. Image columns specifically can store profile photos or logos and display them in apps.
Warning
Choosing the wrong data type early is painful to fix later. If you store "phone number" as a whole number instead of text, you'll lose leading zeros (0207 becomes 207) and can't store extensions like "ext. 412". Plan your column types carefully before your app goes into production.
A row is a single instance of the entity your table represents — one support ticket, one customer, one product. When a user fills out a form in your app and hits Save, they're creating a new row in a Dataverse table.
Every row in Dataverse automatically gets a system-generated primary key called the row's unique identifier — a globally unique ID (GUID) that looks like 3fa85f64-5717-4562-b3fc-2c963f66afa6. You rarely see this ID in your UI, but it's how Dataverse tracks that exact record across its entire database, and it's how lookup relationships know exactly which related row they're pointing to.
Each table also has a primary column — the human-readable field that represents a row's identity. For a Support Ticket table, that might be "Ticket Title." This is what appears in lookup dropdowns when other tables reference this one. Choose your primary column to be something meaningful and unique enough that users can distinguish rows.
Let's walk through actually creating a table so you can see how these concepts come together in the interface. We'll build the Support Ticket table from our example.
Step 1: Open the Dataverse tables area
Go to make.powerapps.com. In the left navigation panel, select Tables. This shows you all tables in your current environment — you'll see Microsoft's standard tables already here.
Step 2: Create a new table
Click New table in the top toolbar, then select Add columns and data from the dropdown. A new dialog opens.
Give your table a Display name: Support Ticket. Notice the Plural display name fills in automatically as Support Tickets — this is used in navigation menus and list views. The Name field (schema name) will be prefixed automatically with your environment's customization prefix.
Optionally, write a Description so other makers who find this table understand what it's for. This is good practice in shared environments.
Step 3: Configure the primary column
Every table needs a primary column. By default it's named "Name" — you'll want to rename this. Click on the primary column header and rename it to Ticket Title. Set the maximum length to something sensible like 200 characters.
Step 4: Add more columns
Click Add column to add each additional field. For the Status column, select Choice as the data type. Dataverse will prompt you to create a new choice or use an existing global choice. Click New choice and define your options:
Label: Open Value: 1
Label: In Progress Value: 2
Label: Waiting Value: 3
Label: Resolved Value: 4
Label: Closed Value: 5
Set the Default value to "Open" so new tickets automatically start in the right state.
For the Priority column, repeat the same process with:
Label: Low Value: 1
Label: Medium Value: 2
Label: High Value: 3
Label: Critical Value: 4
Step 5: Set required fields
Click on your Ticket Title column, then expand Advanced options. Toggle Required to on. This means Dataverse will reject any attempt to save a row without a title — the rule applies regardless of whether the request comes from your app, a Power Automate flow, or an API call.
Step 6: Save and publish
Click Save and publish in the top right. Dataverse creates the table, generates all the system columns, and makes it available for your apps to use.
Tip
Dataverse adds several system columns automatically to every table — things like Created On, Modified On, Created By, and Modified By. You don't need to create these yourself. They're always there in the background, and they're incredibly useful for audit trails and date-based filtering.
When you create a custom table, it starts with a set of system-generated columns that Dataverse adds automatically:
That last one surprises many beginners. Every Dataverse table has a built-in Status column with values "Active" and "Inactive," and a Status Reason column that provides sub-states. "Closed" tickets in our example would typically be set to Status = Inactive. This matters for security roles and views — you can filter your default views to only show Active records, keeping old closed tickets out of the way without deleting them.
You can't delete these system columns, and for good reason — they power Dataverse's built-in security, auditing, and lifecycle management. Work with them, not around them.
If you've used Excel or SharePoint before, here's a translation:
| Excel / SharePoint | Dataverse |
|---|---|
| Workbook / Site | Environment |
| Sheet / List | Table |
| Column header | Column |
| Row | Row / Record |
| Data validation dropdown | Choice column |
| Vlookup to another sheet | Lookup column (relationship) |
| Conditional formatting rule | Business Rule |
The big differences are that Dataverse enforces its rules at the database level (not just in the UI), handles millions of rows gracefully, and has a full security model built in.
Understanding this foundation is especially important when you're deciding which type of app to build. As covered in depth in Model-Driven Apps vs Canvas Apps: When to Use Which Platform, model-driven apps are essentially generated directly from your Dataverse data model — the tables, columns, relationships, and forms you define in Dataverse become the app. Canvas apps give you more visual freedom but still benefit enormously from Dataverse as their data source.
For a broader look at how Dataverse compares to other data sources you might connect to your apps, Connecting Power Apps to SharePoint, Excel, and Dataverse: A Complete Integration Guide is an excellent next read.
One thing that catches beginners off guard is how deeply security is baked into Dataverse at the table and column level. When you create a table, you can configure whether it respects organization-level security (everyone sees all records), owner-based security (users only see records they own), or parent-child security (access follows a relationship to a parent record).
This isn't something you bolt on afterward — it's part of the data model design. Who should see which support tickets? Should agents see all tickets, or only ones assigned to them? Should managers see their team's tickets? The answers to these questions should influence how you design your tables before you write a single formula.
Power Apps Security: Roles, Sharing, and Data Permissions goes deep on this topic, but for now, remember: Dataverse security happens at the row and column level, not just the app level. A user who doesn't have read access to a table won't see that table's data regardless of what your app's UI does.
Key insight
Security in Dataverse is additive. Users have no access by default. You grant access through security roles. This is the opposite of most file-sharing systems where everything is accessible until you lock it down.
Now it's your turn. Follow these steps to build the beginning of a real data model.
Scenario: You're building a simple equipment tracking app for a facilities team. They need to log company equipment (laptops, monitors, phones), track who it's assigned to, and note its condition.
Build this:
Validate your work: After publishing, go to the table and click Edit to open the data editor view. Try adding three rows manually — one laptop in Good condition, one monitor in Fair condition, and one decommissioned phone. Try saving a row without an Asset Name and confirm that Dataverse blocks it with a validation error.
Tip
The data editor (the grid view inside the table editor) is your best friend for quickly testing whether your table works as expected before you build a full app around it. You can add, edit, and delete rows directly here.
Using text columns for everything It's tempting to make every column a text field because it's flexible. Resist this. Storing "Priority" as a free-text field means your data will be inconsistent within weeks. Use Choice columns for anything with a defined set of valid values.
Making too many columns required Start with fewer required columns than you think you need. If users can't complete a row in one sitting, they'll abandon the form or enter fake data to get past the validation. You can always add required constraints later as your process matures.
Confusing the built-in Status with your custom Status Dataverse's built-in Status (Active/Inactive) is separate from your custom "Ticket Status" (Open, In Progress, Resolved). Many beginners create a custom Status choice column and then wonder why there are two status fields on their forms. The built-in one controls record lifecycle; your custom one tracks business process state. Both are useful and serve different purposes.
Forgetting to publish after changes When you make changes to a table — adding a column, changing a label, modifying a choice — those changes are saved in a draft state. They don't appear in your apps until you click Save and publish. If you add a column and don't see it in your app, this is almost always why.
Choosing Date and Time when you only need Date If you create a Date and Time column for something like "Date of Birth" or "Due Date," Dataverse will store the time component too, which can cause off-by-one-day errors depending on timezone settings. Use Date Only for anything where the time doesn't matter.
Naming columns with spaces in the schema name
The display name of a column can have spaces ("First Name"), but the schema name (used in formulas) uses underscores (firstname or cr5a2_first_name). When writing Power Fx formulas, you'll reference the schema name, so keeping those clean and readable saves headaches later.
Warning
Deleting a column from a published table is permanent and irreversible if any data has been stored in it. Before deleting a column you think you don't need anymore, check whether any Power Automate flows, other apps, or business rules reference it. The platform will warn you if there are dependencies, but it won't catch everything.
You've now got a solid foundation in how Dataverse organizes data. Let's recap the key ideas:
This understanding is the foundation for everything else in the Model-Driven Apps & Dataverse learning path. Your next steps should be:
As you start building apps on top of your Dataverse data models, you'll also want to understand Power Apps Data Sources Explained: Tables, Records, and Collections for Absolute Beginners for how the Power Apps formula language sees and works with your Dataverse tables.
The data model you design in Dataverse is the backbone of everything your app can do. Get it right, and your apps are a joy to build and use. Get it wrong, and you'll be fighting your own data structure at every step. Now that you understand the fundamentals, you have everything you need to design it right.
Model-Driven Apps & Dataverse