Write Once, Reuse Everywhere: DAX UDFs in Power BI
Inkey Solutions, June 2, 202654 Views
Power BI’s DAX (Data Analysis Expressions) language has long been a cornerstone for creating dynamic calculations in data models. With the introduction of DAX User-Defined Functions (UDFs) in the September 2025 preview update, Power BI users can now create reusable, parameterized functions to streamline and enhance their analytics workflows.
In this blog, we’ll explore what DAX UDFs are, their uses, when to leverage them, how to implement them, and their advantages and limitations.
Overview of DAX User-Defined Functions
DAX UDFs are custom functions you can define in Power BI using the DAX language. Unlike built-in DAX functions (e.g., SUM or AVERAGE), UDFs are user-created, stored as first-class objects in your semantic model, and can be reused across measures, calculated columns, visual calculations, or even other UDFs. They support up to 12 parameters, allowing for flexible, modular calculations. UDFs can return scalars (like numbers or text), tables, or even more complex structures, making them versatile.
Key enhancements in the September 2025 release include:
- VAL mode for eagerly evaluated parameter values
- EXPR mode for lazily evaluated expressions that respect filter context
- Optional type hints (NUMERIC, TEXT, TABLE, etc.) to enforce data types and catch errors early
What Is DAX UDFs Used For?
DAX UDFs are designed to encapsulate reusable logic, making them ideal for:
- Standardizing Calculations: Create a single function for repetitive calculations, like tax rates, discounts, or statistical metrics (e.g., weighted averages).
- Simplifying Complex Logic: Break down intricate DAX expressions into modular, readable functions.
- Visual Enhancements: Generate dynamic visualizations, such as SVG-based charts for actual vs. previous year comparisons.
- Centralized Maintenance: Update logic in one place to propagate changes across all dependent measures or columns.
- Advanced Analytics: Build functions for machine learning-like operations (e.g., simple forecasting) or integrations with other DAX features like time intelligence.
- Data Transformation: Create table-returning UDFs for custom filtering or aggregation, such as generating a top N list based on parameters.

When to Use DAX UDFs
Use DAX UDFs when:
- Repetitive Logic Exists: You’re repeating the same calculation (e.g., tax, growth percentage) across measures, columns, or visuals.
- Parameterized Calculations Are Needed: You require dynamic inputs, like variable tax rates or thresholds, that can be passed as parameters.
- Model Maintenance Is a Priority: You want to centralize logic to avoid updating multiple measures or columns manually.
- Complex Calculations Need Simplification: You’re working with layered or nested DAX that’s hard to maintain or debug.
- Reusable Visuals Are Desired: You need consistent visual calculations, like SVG bars or custom formatting, across reports.
- Scalability for Teams: In collaborative environments, UDFs promote code sharing and standardization.
When NOT to Use:
- For one-off, report-specific calculations where a simple measure suffices (e.g., Total Sales = SUM(Sales [Amount])).
- When performance testing hasn’t been done, UDFs are in preview (as of September 2025) and may have evolving behavior.
- If your team lacks DAX expertise, as UDFs require understanding parameter modes (VAL/EXPR) and type hints.
- For recursive operations, UDFs do not support recursion.
- In very large models without profiling, as excessive nesting might impact performance.
Understanding Parameter Modes and Types
To make UDFs more powerful, DAX introduces parameter modes and types:
- Modes:
- VAL: The parameter is evaluated immediately when passed (eager evaluation). Use for simple values like numbers or strings.
- EXPR: The parameter is evaluated lazily, only when used inside the function. Ideal for expressions that depend on context, like table filters.
- Types (optional hints for safety):
- NUMERIC: For numbers.
- TEXT: For strings.
- TABLE: For table expressions.
- LOGICAL: For TRUE/FALSE.
- And more (e.g., DATE, ROW).
/// Filters a table where Sales exceeds a given threshold
FUNCTION FilterTable = ( tbl: TABLE EXPR, threshold: NUMERIC VAL ) =>
FILTER(tbl, [Sales] > threshold)
Tip: Use VAL for fixed scalars and EXPR for anything that involves a table or needs to respect the calling filter context.
How to Use DAX UDFs in Power BI
Here’s a step-by-step guide to creating and using a DAX UDF in Power BI Desktop:
- Enable the Preview Feature: Go to File > Options and settings > Options > Preview features. Check ‘DAX user-defined functions’, click OK, and restart Power BI Desktop.
- Open DAX Query View: In the Modeling tab, click New query (or Ctrl + Alt + Q) to open DAX Query View.
- Define the UDF: Write your UDF using the syntax below. Always include /// comments for documentation.
/// Description of what the function does
FUNCTION FunctionName = ( Parameter: Type Mode, … ) => Expression
- Test It: Use EVALUATE to test your function before saving to the model.
/// Adds 10% tax to an amount
FUNCTION AddTax = ( amount: NUMERIC VAL ) => amount * 1.1EVALUATE { AddTax(100) }
–Expected output: 110
- Add to Model: Click Update model via CodeLens or right-click to save. Verify it appears under the Functions node in Model Explorer.
- Use the UDF: Call the UDF inside measures, calculated columns, or visual calculations.
// In a Measure
Total with Tax = SUMX(Sales, AddTax([Amount]))
// In a Calculated Column
Taxed Amount = AddTax(Sales[Amount])
- Test and Publish: Save your .pbix file and publish to Power BI Service. UDFs work in the service but require Desktop with the preview feature enabled for editing.
Real Life Examples
Example 1: Year-over-Year Growth (Scalar UDF)
YoY growth is one of the most repeated calculations in Power BI reports. Define it once and call it across every metric.
/// Calculates Year-over-Year percentage growth
/// @param currentValue: Current period value
/// @param previousValue: Previous period value
FUNCTION YoYGrowth = ( currentValue: NUMERIC VAL, previousValue: NUMERIC VAL ) =>
DIVIDE(currentValue -previousValue, previousValue, 0)EVALUATE { YoYGrowth(120000, 100000) }
–Expected output: 0.20 (20%)
Usage -apply the same logic to any metric without repeating DIVIDE logic:
VAR current = [Total Revenue]
VAR previous = CALCULATE([Total Revenue], SAMEPERIODLASTYEAR(‘Date'[Date]))
RETURN YoYGrowth(current, previous)Profit YoY % =
VAR current = [Total Profit]
VAR previous = CALCULATE([Total Profit], SAMEPERIODLASTYEAR(‘Date'[Date]))
RETURN YoYGrowth(current, previous)Units YoY % =VAR current = [Total Units]
VAR previous = CALCULATE([Total Units], SAMEPERIODLASTYEAR(‘Date'[Date]))
RETURN YoYGrowth(current, previous)
Example 2: Top N Products by Sales (Table-Returning UDF)
Table-returning UDFs are where DAX UDFs truly shine. This example creates a reusable function that returns the top N products above a minimum sales threshold.
/// Returns Top N products above a minimum sales threshold
/// @param n: Number of top products to return
/// @param threshold: Minimum sales amount to qualify
FUNCTION TopProducts = ( n: NUMERIC VAL, threshold: NUMERIC VAL ) =>
TOPN(
n,
FILTER(
SUMMARIZE(
Sales,
Products[ProductName],
“Total Sales”, SUM(Sales[Amount])
),
[Total Sales] > threshold
),
[Total Sales], DESC
)EVALUATE TopProducts(5, 10000)
–Returns a table of top 5 products with sales above 10,000
Usage in a measure:
Top 5 Product Revenue = SUMX(TopProducts(5, 10000), [Total Sales])
How DAX UDFs Behave in a Live Model
Once you click Update Model in DAX Query View, your UDF becomes a first-class citizen of the semantic model. Here is what that means in practice:
Storage and Visibility
- UDFs are stored directly inside the .pbix file as part of model metadata
- They appear under the Functions node in Model Explorer, separate from measures and calculated columns
- They are visible to all report authors working on the same model
Dependency Tracking
- Power BI tracks UDF dependencies automatically -if a UDF is used in 10 measures, Model Explorer shows all 10 as dependents
- Deleting or renaming a UDF that has dependents triggers a dependency warning, preventing accidental breakage
- You can inspect the full dependency chain using the lineage view in Model Explorer
Filter Context Behavior
- UDFs fully respect the filter context of wherever they are called -a UDF called inside a visual evaluates under that visual’s row and filter context
- VAL parameters are evaluated before entering the function, capturing the outer context at call time
- EXPR parameters are evaluated inside the function, respecting any context shifts applied within the UDF such as inside a CALCULATE
Refresh and Service Behavior
- UDFs survive dataset refreshes as they are part of model definition, not data
- They work fully in Power BI Service for consumption, but editing requires Power BI Desktop with the preview feature enabled
- When publishing, UDFs are bundled with the model and available immediately to all report consumers
Impact of Editing a UDF
- Changing a UDF’s logic propagates instantly to every measure or column that calls it -no individual updates needed
- If you change a parameter type or remove a parameter, dependent measures using the old signature will show a formula error until updated
- Always test UDF changes in a staging model before updating production reports
Best Practices for DAX UDFs
- Naming: Use descriptive, PascalCase names; avoid reserved words.
- Documentation: Always add /// comments for descriptions and parameter info.
- Type Hints: Use them to prevent type mismatches.
- Modularity: Keep functions small and focused; chain UDFs if needed.
- Performance: Test with DAX Studio for query plans; avoid deep nesting.
- Version Control: Use external tools like Tabular Editor for managing UDFs in larger models.
- Sharing: Contribute to community libs like daxlib.org.
Common Pitfalls and Troubleshooting
- Error: Invalid Parameter Name: Avoid periods or spaces; use underscores.
- Performance Issues: UDFs in preview may not optimize fully—profile with Performance Analyzer.
- Mode Mismatch: Use EXPR for context-dependent params to avoid evaluation errors.
- Debugging: Use EVALUATE with sample data; check Model Explorer for dependencies.
- Preview Limitations: Features may change; back up models before updating.
Pros of DAX UDFs
- Reusability: Define once, use everywhere—reduces code duplication.
- Maintainability: Update a UDF in one place to propagate changes across the model.
- Modularity: Encapsulate complex logic for cleaner, more readable DAX.
- Flexibility: Parameters (up to 12) and modes (VAL/EXPR) allow dynamic calculations.
- Performance: Can reduce formula engine overhead in layered calculations.
- Type Safety: Optional type hints (e.g., NUMERIC, TABLE) reduce errors.
- Integration: Works seamlessly with visual calculations and semantic models.
Cons of DAX UDFs
- Learning Curve: Requires understanding DAX, parameter modes, and type hints, which may be challenging for beginners.
- Naming Restrictions: Function and parameter names must avoid reserved words and follow strict conventions (e.g., no periods in parameter names).
- Limited Parameters: Capped at 12 parameters, which may constrain very complex functions.
- No Recursion: UDFs cannot call themselves, limiting certain use cases.
- Dependency on Measures/Columns: UDFs must be used within measures or columns for visuals, unlike calculation groups.
- Potential Overhead: In large datasets, unoptimized UDFs might slow queries—always test.
Conclusion
DAX User-Defined Functions are a game-changer for Power BI users, offering a modular, reusable way to manage DAX calculations. They shine in scenarios requiring repetitive or complex logic, such as tax calculations, statistical metrics, or custom visualizations. While their preview status (as of September 2025) calls for careful testing, their benefits in maintainability and flexibility make them a powerful addition to your Power BI toolkit.
To get started, enable the preview feature, experiment with simple UDFs in DAX Query View, and explore community libraries for inspiration. Check out resources like the official Microsoft documentation or SQLBI articles for more depth. As UDFs evolve, they’re poised to become a staple for advanced Power BI modelers. Have you tried UDFs yet? Share your experiences or questions in the comments!











