In a previous article, Introducing user-defined functions in DAX, we introduced the syntax and the capabilities of this feature that was introduced in preview in September 2025. While there could be many ways to categorize functions, every function can be one of the following:
- Model-independent function – Has no references to specific tables, columns, calendars, or measures within a semantic model. A model-independent function can have dependencies on other model-independent functions, but it cannot depend on a model-dependent function.
- Model-dependent function – Has one or more direct or indirect references to specific tables, columns, calendars, measures, or other model-dependent functions within a semantic model.
This distinction is essential for clarifying the characteristics that a function must have, depending on its designed scope and context of utilization. In general, user-defined functions in DAX are the primary method for reusing DAX code. However, you may want to reuse the same code in different models or just within a specific semantic model, and this leads to different requirements for the function code.
Defining model-dependent functions
A model-dependent function has one or more dependencies on specific objects, such as columns, tables, or measures. For example, a function that includes a reference to the Date[Date] column or to the Customer table is a function that has a dependency on the semantic model. Such function cannot be copied into another semantic model unless all the dependencies also exist in the target semantic model. Unfortunately, the function does not explicitly declare these dependencies, so the existing user interfaces for creating and editing functions do not validate the presence of these constraints before completing a “paste” operation.
For example, this is the implementation of a RangeLookup user-defined function that relies on a Price Range table that has the columns Min, Max, and Range:
PriceLookup = (
searchValue : VAL
) =>
SELECTCOLUMNS (
FILTER (
'Price Range',
'Price Range'[Min] <= searchValue && 'Price Range'[Max] > searchValue
),
'Price Range'[Range]
)
The model-dependent functions are intended to reside within a semantic model and serve as the primary means of sharing DAX code across the same semantic model. Therefore, model-dependent functions are tightly coupled with the model and tend to have a small number of parameters. The primary goal is to simplify the execution of code shared in the same model.
Model-dependent functions are convenient and readable within the context of a single model, but they are not portable to other models. Changing objects in the semantic model may break existing model-dependent functions. Therefore, it is advisable to create queries or scripts to test the validity of each function in the semantic model.
Defining model-independent functions
A model-independent function does not have any dependency on specific columns, tables, or measures. All the dependencies are specified in function parameters. The function caller is responsible for providing valid parameters to the function.
Because of the longer list of parameters, a model-independent function is usually more verbose than its corresponding model-dependent counterpart. For example, here is the code of RangeLookup, a model-independent implementation of PriceLookup:
RangeLookup = (
searchValue : SCALAR VAL,
lookupTable : ANYREF EXPR,
minColumn : ANYREF EXPR,
maxColumn : ANYREF EXPR,
targetColumn : ANYREF EXPR
) =>
SELECTCOLUMNS (
FILTER (
lookupTable,
minColumn <= searchValue && maxColumn > searchValue
),
targetColumn
)
The code for RangeLookup can be easily integrated into any semantic model, as it only depends on its parameters and has no dependencies on specific tables, columns, measures, or relationships. DAX libraries published on https://daxlib.org can only contain model-independent functions; model-dependent functions are not permitted in public DAX libraries.
When a model-independent function is imported into a model, you can simplify its model-specific use by creating a corresponding, model-dependent function that reduces the number of parameters. For example, this is the implementation of the model-dependent PriceRangeLookup function, which internally utilizes the model-independent PriceRange function:
PriceRangeLookup = (
searchValue : VAL
) =>
RangeLookup(
searchValue,
'Price Range',
'Price Range'[Min],
'Price Range'[Max],
'Price Range'[Range]
)
Model-dependent vs. model-independent functions
The following table provides a quick recap of the differences between model-dependent and model-independent functions.
| Aspect | Model-dependent | Model-independent |
| References | Uses specific model objects (tables, columns, measures, relationships) | Uses only parameters passed by the caller |
| Portability | Bound to a specific model | Reusable across models |
| Ease of use | More concise and readable in context | More verbose, requires passing all dependencies |
| Maintenance | Sensitive to schema changes | Stable across schema variations |
| Use case | Production reports, model-tied logic | Reusable libraries, shared calculations |
| Failure risk | Breaks if model objects change | Works as long as parameters are valid |
| Typical audience | Report developers | DAX library authors, advanced users |
Hidden dependency issues in table expressions
Model dependency seems like an easy property to check: a function either does or does not have references to model objects. However, there is a blurry line when the parameter is a table. Some functions appear model-independent but implicitly assume a specific table structure.
If the function accesses specific columns of a table passed as an argument, the function is making an assumption about the shape of the table provided. This is an actual dependency from an external structure (the table) that must satisfy specific prerequisites – such as the presence of a column with a particular name.
For example, consider the following function:
SumAmount = (
transactionsTable : TABLE
) =>
SUMX (
transactionsTable,
[Quantity] * [Net Price]
)
The Quantity and Net Price columns should exist in the transactions table to successfully execute the SumAmount function. Therefore, SumAmount is a function that depends on a particular structure of the transactionsTable parameter. Unfortunately, this dependency cannot be expressed programmatically using specific keywords. The function author can only add notes to the function’s comment.
If the transactionsTable argument does not include both the Quantity and the Net Price columns, the execution of SumAmount will fail. While we could consider this dependency “weaker” than the direct reference to a model object, it is still a dependency that makes the code harder to reuse. Therefore, these functions are also considered model-dependent because they rely on the existence of specific columns, not on model binding.
If we want to make SumAmount a model-independent function, we must expose all the internal columns and measure references as EXPR parameters. For example, here is a model-independent version of the previous SumAmount function:
SumAmountIndependent = (
transactionsTable : TABLE EXPR,
quantityColumn : ANYREF EXPR,
priceColumn : ANYREF EXPR
) =>
SUMX (
transactionsTable,
quantityColumn * priceColumn
)
The SumAmountIndependent function can be published in a shared DAX library and its use can be simplified by defining the following model-dependent function that has no parameters:
SumAmountModel = ( ) =>
SumAmountIndependent (
Sales,
Sales[Quantity],
Sales[Net Price]
)
Naming conventions for user-defined functions
The DAX syntax does not enforce a standard on the names of functions and their parameters. However, both for usability and readability reasons, it is highly recommended to respect naming conventions. This is also to avoid conflicting names in different libraries that could be imported into the same model. A more complete and updated summary of naming conventions is available at DAX Naming Conventions.
Function names
Function names should be written in Pascal case, using a dot character (.) to categorize functions – something that corresponds to the namespaces in several programming languages. Use “Local.” as a prefix for model-dependent functions to avoid conflicts with future DAX function names. Model-independent functions should have names starting with the corresponding library name.
Here are some examples of model-dependent functions: GetCustomerDiscount, Local.GetCustomerDiscount, Local.Checkout.GetCustomerDiscount.
The following are examples of model-independent functions: Math.SumTwoNumbers, Math.Common.SumTwoNumbers, CompanyName.Math.SumTwoNumbers. In these examples, Math is the library name; use the CompanyName prefix if you create multiple libraries shared across the company.
You cannot use Dax and other DAX keywords (returned by the DISCOVER_KEYWORDS data-management view) as a part of the compound name of a function.
Parameters
Use camelCase for parameter names. For the EXPR passing mode, also and include a suffix indicating the parameter type. This way, when you read the code of the DAX function you can see where to expect a context transition (Measure), where a column reference is used (Column), and where you are manipulating a table (Table). The following suffixes are designated for EXPR parameters:
- Column for a column reference.
- Table for a table reference.
- Measure for a measure reference.
- Expr for a DAX expression that is not necessarily a single column reference, table reference, or measure reference.
- Calendar for a calendar reference, which cannot be an expression.
Examples of EXPR parameter names: lookupTable, listPriceColumn, amountMeasure, and metricExpr.
Conclusions
Understanding the model dependency of a function is crucial for maintainability and reuse. Use model-independent functions for libraries, and model-dependent functions to simplify access to functions in other DAX expressions.
Name the function and its parameters according to the naming conventions to make it easier to read the function code and to provide the correct arguments when you call a function. Use https://daxlib.org to access many public, free, open-source libraries of DAX model-independent functions that are ready to use!