Guide ยท Last reviewed: September 2026
A complete naming convention for Microsoft Fabric
Every Fabric item type, every pipeline activity, and the three things most conventions leave out entirely: variables, parameters and connections. Written to be followable by an agent, not just readable by a person.
- 51
- Item types
- 37
- Pipeline activities
- September 2026
- Last reviewed
- Verified
- Against REST enums
The pattern
Everything below is one pattern with optional segments:
[ENV_][LAYER_]TYPE_DOMAIN_Description[_Qualifier]| Segment | When to use it | Allowed values | Casing |
|---|---|---|---|
ENV | Only when items from more than one environment sit side by side | DEV, TST, UAT, PRD | Upper |
LAYER | On workspace items. Dropped on objects inside a lakehouse or warehouse | ING, VAL, CUR, PRS | Upper |
TYPE | Always, on anything a developer touches | From the tables below | Upper |
DOMAIN | Always on any surface shared beyond one team | Your project or domain code, e.g. DNA | Upper |
Description | Always | What it does | PascalCase, words joined with _ |
Qualifier | Optional | MI, DL, Import, Inc, Full | Mixed |
So ING_DP_DNA_Product_Sales is an ingestion-layer data pipeline in the DNA domain loading product and sales. That's the same example from the original post, and it still holds.
The rules behind it
If you're handing this to an agent, or to a new starter, these are the parts that matter:
That last one is the one that tends to go first, usually with a person's initials or a ticket number.
Item types
This is what the original post was missing. Codes are two to five uppercase letters, and every row below comes from the ItemType enumeration in the List Items REST API reference, which is the authoritative list of what Fabric considers an item. That page was last updated at the end of August 2026 and carried 51 types when I checked.
Two things to know before you use these. The enum says "additional item types may be added over time", so this is a snapshot and the list will grow. And a handful of these types are created by Fabric, not by you, so they never get named by hand at all.
Data Engineering item codes 5
| Item | Code | API type | Example |
|---|---|---|---|
| Lakehouse | LH | Lakehouse | ING_LH_DNA |
| Notebook | NB | Notebook | ING_NB_DNA_Product_Dedupe |
| Apache Spark job definition | SJD | SparkJobDefinition | CUR_SJD_DNA_Sales_Aggregate |
| Environment | ENV | Environment | ENV_DNA_Spark35 |
| SQL analytics endpoint | SQLEP | SQLEndpoint | created by Fabric |
Data Factory item codes 7
| Item | Code | API type | Example |
|---|---|---|---|
| Data Pipeline | DP | DataPipeline | ING_DP_DNA_Product_Sales |
| Dataflow Gen2 | DF | Dataflow | VAL_DF_DNA_Customer_Clean |
| Copy Job | CJ | CopyJob | ING_CJ_DNA_Sales_Incremental |
| Variable Library | VL | VariableLibrary | VL_DNA_Sales |
| Apache Airflow Job | AAJ | ApacheAirflowJob | ING_AAJ_DNA_Vendor_Feeds |
| dbt job | DBT | DataBuildToolJob | CUR_DBT_DNA_Sales_Build |
| Azure Data Factory (mounted) | MDF | MountedDataFactory | ING_MDF_DNA_Legacy_ADF |
Data Warehouse and database item codes 6
| Item | Code | API type | Example |
|---|---|---|---|
| Warehouse | WH | Warehouse | CUR_WH_DNA |
| Warehouse Snapshot | WHS | WarehouseSnapshot | CUR_WHS_DNA_MonthEnd |
| SQL Database | SQLDB | SQLDatabase | CUR_SQLDB_DNA_Sales |
| Cosmos DB Database | CDB | CosmosDBDatabase | ING_CDB_DNA_Events |
| Snowflake Database | SFDB | SnowflakeDatabase | ING_SFDB_DNA_Iceberg |
| Datamart | DM | Datamart | retired, list-only |
Mirroring item codes 5
| Item | Code | API type | Example |
|---|---|---|---|
| Mirrored Database | MIR | MirroredDatabase | ING_MIR_DNA_SalesDB |
| Mirrored Warehouse | MWH | MirroredWarehouse | created by Fabric |
| Mirrored Azure Databricks Catalog | MADC | MirroredAzureDatabricksCatalog | ING_MADC_DNA_Bronze |
| Mirrored Catalog | MCAT | MirroredCatalog | ING_MCAT_DNA_Iceberg |
| Azure Databricks Storage | ADBS | AzureDatabricksStorage | ING_ADBS_DNA_Delta |
Real-Time Intelligence item codes 7
| Item | Code | API type | Example |
|---|---|---|---|
| Eventhouse | EH | Eventhouse | ING_EH_DNA_Telemetry |
| KQL Database | KQLDB | KQLDatabase | ING_KQLDB_DNA_Clickstream |
| KQL Queryset | KQS | KQLQueryset | VAL_KQS_DNA_Session_Checks |
| Real-Time Dashboard | RTD | KQLDashboard | PRS_RTD_DNA_Operations |
| Eventstream | ES | Eventstream | ING_ES_DNA_Orders_Live |
| Activator | ACT | Reflex | CUR_ACT_DNA_Stock_Alert |
| Event Schema Set | ESS | EventSchemaSet | ING_ESS_DNA_Orders |
Data Science and AI item codes 5
| Item | Code | API type | Example |
|---|---|---|---|
| ML Model | MDL | MLModel | CUR_MDL_DNA_Churn |
| Experiment | EXP | MLExperiment | CUR_EXP_DNA_Churn_Tuning |
| Fabric data agent | DA | DataAgent | PRS_DA_DNA_Sales |
| Anomaly detection | AD | AnomalyDetector | CUR_AD_DNA_Spend |
| Operations Agent | OA | OperationsAgent | CUR_OA_DNA_Ops |
Power BI item codes 7
| Item | Code | API type | Example |
|---|---|---|---|
| Semantic Model | SM | SemanticModel | CUR_SM_DNA_Sales_MI |
| Report | RPT | Report | PRS_RPT_DNA_Sales_Overview |
| Paginated Report | PRPT | PaginatedReport | PRS_PRPT_DNA_Invoice |
| Dashboard | DSH | Dashboard | PRS_DSH_DNA_Executive |
| Org App | APP | OrgApp | APP_DNA_Sales |
| Org App Audience | APPA | OrgAppAudience | APPA_DNA_Sales_Finance |
| App Backend | APPB | AppBackend | undocumented |
Graph, ontology and specialist item codes 9
| Item | Code | API type | Example |
|---|---|---|---|
| API for GraphQL | GQL | GraphQLApi | PRS_GQL_DNA_Sales |
| Graph Model | GMDL | GraphModel | CUR_GMDL_DNA_Customer |
| Graph Queryset | GQS | GraphQuerySet | VAL_GQS_DNA_Paths |
| Ontology | ONT | Ontology | CUR_ONT_DNA_Retail |
| User Data Function | UDF | UserDataFunction | VAL_UDF_DNA_Validate_Postcode |
| Digital Twin Builder | DTB | DigitalTwinBuilder | CUR_DTB_DNA_Store |
| Digital Twin Builder Flow | DTBF | DigitalTwinBuilderFlow | CUR_DTBF_DNA_Store_Load |
| Map | MAP | Map | PRS_MAP_DNA_Territories |
| Plan | PLN | Plan | CUR_PLN_DNA_Forecast |
The MI on the semantic model is a qualifier for storage mode, Import. DL for Direct Lake, DQ for DirectQuery. It's a useful thing to know before you open a model, and it stops two models with the same job from having the same name.
One deliberate omission. I haven't marked anything GA or preview. The status is findable if you go page by page through Learn, but it changes every month and it doesn't affect what you call something, so it would be stale here faster than the rest of this post.
Two gaps in that enum worth knowing about. Some items you create in the portal have no API type at all, Scorecards and Explorations among them, so a script that enumerates items by type won't see them even though you still have to name them. And some enum values are child items or system-created, so they never reach a naming decision: the SQL analytics endpoint and mirrored warehouse are made for you, Org App Audience and Digital Twin Builder Flow are children of their parent item, and AppBackend isn't documented anywhere I could find.
Pipeline activities
The original post gave two activity examples. Here's the full set.
A note on where these come from, because it's not where you'd look first. The Fabric activity documentation pages are all UI walkthroughs with no JSON in them. The authoritative list of activity type strings lives in the REST API item definition reference, which documents the DataPipelineActivityTypes enum in full. If you're generating pipelines programmatically, that's the page to bookmark, not the activity docs.
Data movement and transformation activity codes 10
| Activity (UI name) | Code | JSON type |
|---|---|---|
| Copy data | CD | Copy |
| Copy job | CJ | InvokeCopyJob |
| Dataflow | DF | RefreshDataFlow |
| Notebook | NB | TridentNotebook |
| Spark Job Definition | SJD | SparkJobDefinition |
| Script | SCR | Script |
| Stored procedure | SP | SqlServerStoredProcedure |
| Delete data | DEL | Delete |
| Azure HDInsight | HDI | AzureHDInsight |
| Invoke SSIS Package | SSIS | ExecuteSSISPackage |
Control flow activity codes 17
| Activity (UI name) | Code | JSON type |
|---|---|---|
| If Condition | IF | IfCondition |
| Switch | SW | Switch |
| ForEach | FE | ForEach |
| Until | UNT | Until |
| Filter | FLT | Filter |
| Wait | WAIT | Wait |
| Fail | FAIL | Fail |
| Set Variable | SV | SetVariable |
| Append Variable | AV | AppendVariable |
| Get Metadata | GM | GetMetadata |
| Lookup | LKP | Lookup |
| Invoke pipeline | IP | InvokePipeline |
| Invoke pipeline (Legacy) | IPL | ExecutePipeline |
| Web | WEB | WebActivity |
| WebHook | WHK | WebHook |
| Functions | FN | AzureFunction |
| KQL | KQL | KustoQueryLanguage |
External compute activity codes 4
| Activity (UI name) | Code | JSON type |
|---|---|---|
| Azure Batch | AB | Custom |
| Azure Databricks | ADB | DatabricksNotebook |
| Azure Machine Learning | AML | AzureMLExecutePipeline |
| Azure Data Lake Analytics | ADLA | DataLakeAnalyticsScope |
Fabric maintenance and refresh activity codes 5
| Activity (UI name) | Code | JSON type |
|---|---|---|
| Semantic model refresh | SMDR | PBISemanticModelRefresh |
| Lakehouse Maintenance | LHM | not published |
| Refresh SQL analytics endpoint | RSE | not published |
| Refresh Materialized Lake View | RMV | not published |
| Approval | APR | not published |
Notification activity codes 2
| Activity (UI name) | Code | JSON type |
|---|---|---|
| Office 365 Outlook | OL | Office365Email |
| Teams | TM | MicrosoftTeams |
I kept SMDR for the semantic model refresh because that's what the original post used, so anyone who picked it up from there already has it. On the scheme's own logic it should be SMR, and if you're starting fresh that's the tidier choice.
For the activity name itself, the pattern is the code plus what it operates on. Copy activities read better with the direction spelled out:
CD_SalesAPI_To_LH_SalesLKP_Watermark_SalesFE_Product_BatchesSMDR_DNA_SalesIF_RowCount_GreaterThanZero
Inside a ForEach, the child activities don't need the loop's name repeated. The pipeline canvas already nests them.
You'll notice some codes appear in both the item tables and the activity tables. NB, SJD, CJ and DF are deliberately the same in both places, because the activity runs the item of that name and having them match is one less thing to remember. The one I did split is WH, which is the Warehouse item, so the WebHook activity gets WHK.
Four traps in the activity names
These are worth knowing before you standardise on anything:
- The UI name and the JSON type disagree more often than you'd expect. "Office 365 Outlook" is
Office365Email. "Copy data" isCopy. "Notebook" isTridentNotebook, which is the old internal name for Fabric. If your naming convention is enforced by a script reading pipeline definitions, it has to match on the JSON type, not the friendly name. - There are two Invoke pipeline activities with different type strings and different shapes.
ExecutePipelinetakes a pipeline reference by name and only works in the same workspace.InvokePipelinetakes a workspace ID and pipeline ID and works across workspaces. The enum labelsInvokePipelineas deprecated, but the Fabric UI docs describe the legacy one as the limited one, so the two sources contradict each other. Go by which shape you're using. - Deactivating an activity isn't an activity. It's a state property on any activity, so there's nothing to name.
- UI casing is genuinely inconsistent.
Set VariableandLakehouse Maintenanceare title case,Semantic model refreshandRefresh SQL analytics endpointare sentence case. Don't spend time trying to find the rule, there isn't one.
Variables and parameters
I skipped these entirely last time, and they're where inconsistency does the most damage, because they show up inside expressions, not in a list you can scan.
The distinction that drives the naming: a parameter is set when the run starts and stays put for the whole run. A variable can be changed mid-run with a Set Variable activity. So the name should tell you which one you're looking at, and prefixes do that better than anything else here.
| Kind | Prefix | Example | Referenced as |
|---|---|---|---|
| Pipeline parameter | p_ | p_LoadDate | @pipeline().parameters.p_LoadDate |
| Pipeline variable | v_ | v_RowCount | @variables('v_RowCount') |
| Array variable | v_ + plural noun | v_FileNames | @variables('v_FileNames') |
| Library variable | lv_ | lv_SalesApiBaseUrl | @pipeline.libraryVariables.lv_SalesApiBaseUrl |
| Pipeline return value | rv_ | rv_RowsLoaded | Set Variable, in return value mode |
Lowercase prefix, PascalCase after it. The reason for lowercase is purely practical: in an expression, @variables('v_RowCount') has the prefix visually out of the way, and a screen full of @variables('V_ROWCOUNT') is harder to read than it needs to be.
Make the array ones plural. Append Variable only works on arrays, so when you see v_FileNames you already know an append is legal and when you see v_FileName you know it isn't.
What the types are
Variables in Fabric pipelines are String, Bool or Array. That's three, and it's stated plainly in the Set Variable activity docs.
Parameters are the awkward one. The Fabric parameters documentation says you give a parameter a name, a data type and a default value, and then never lists the data types anywhere. The usual list you'll see quoted, String, Int, Float, Bool, Array, Object and SecureString, comes from the Azure Data Factory documentation, which is scoped to ADF and Synapse. It's very likely right, since Fabric pipelines inherit the engine, but I haven't found it stated for Fabric, and SecureString in particular has no Fabric mention at all. Worth knowing if you're writing a standard you expect to hold.
Which means parameters can hold types variables can't, Object and Int among them. If you need an integer that changes during the run, you're storing it in a String variable and casting it. Naming it v_RowCount and having it be a string is a small honesty problem worth being aware of.
Variable libraries are a different thing
A Variable Library is its own workspace item, not a pipeline variable. It's the CI/CD configuration bucket, holding a value set per stage, and it's the documented replacement for ADF global parameters. Pipelines read from it and can't write to it.
It supports Boolean, Datetime, Guid, Integer, Number and String, with one trap: Number isn't supported in pipelines, and Datetime and Guid arrive as String. So a library variable named lv_RefreshDate is a string on the other side, whatever the library says it is.
This is where the environment prefix belongs, incidentally. Instead of DEV_ on every item, put the environment-varying values in a variable library and let the deployment pick the value set.
Connections
In Fabric, what ADF called a linked service is a connection, and "linked service" isn't a Fabric concept at all. It only appears in the docs to describe what you're migrating from. Datasets are gone too, with data properties now defined inline on the activity.
The thing that changes how you name them: connections don't live in a workspace. They're managed from the tenant settings, under Manage connections and gateways, and they're visible per principal, meaning you only see connections you've been given access to, even as a tenant admin. The REST path is /v1/connections with no workspace ID in it.
So a connection name can't lean on workspace context the way an item name can. It has to stand on its own, and it has to include the environment, because the DEV and PROD connections to the same system are two objects sitting in the same list.
CN_<ConnectorType>_<Target>_<ENV>CN_SQL_AdventureWorks_PRDCN_ADLS_SalesLanding_DEVCN_REST_SalesAPI_UATCN_SFTP_VendorDrop_PRD
Connection roles are User, UserWithReshare and Owner in the API, shown as User, User with resharing and Owner in the UI. Worth getting UserWithReshare right in scripts, it's a name people guess wrong.
The parameterisation gotcha
In ADF you could parameterise a linked service and swap the server or database at runtime. Fabric connection properties can't be parameterised. What you parameterise instead is which connection gets used, by putting the connection's GUID in a parameter. You'll find the GUID under Manage connections and gateways, Settings, Connection ID.
That's a naming problem as much as a plumbing one, because you end up with parameters holding GUIDs, and a GUID tells you nothing when you're reading a pipeline. Name the parameter after the connection it points at, so p_ConnSalesDB holding the GUID of CN_SQL_AdventureWorks_PRD at least reads as intentional. Better still, hold those GUIDs in a variable library keyed by environment, and the pipeline stops caring.
Inside a lakehouse or warehouse
Unchanged from the original post, and the reasoning still stands. At this level I drop the transformation layer prefix, because as a developer you already know which lakehouse you're in.
In ING_LH_DNA:
DNA_Dim_ProductsDNA_Fact_Sales
Columns in snake case with capitalised words: Product_Name, Product_ID.
For mesh architectures with multiple domains or products, prefix with domain and product: Domain_Product_TableType_Name.
Two things I'd add to what I wrote before. Schemas in a warehouse do some of this work for you, so if you're using them, a curated schema means the table doesn't need CUR in its name. And in a semantic model, measures don't take the type prefixes at all. They're business objects, so they get business names, and they're the objects your users see most.
The presentation layer
Same rule as before, and it's the one I'd defend hardest: anything shared outside the developer zone doesn't use developer naming conventions. It uses business naming.
Which surfaces count depends on how you distribute:
- Distribution through a Power BI or Fabric app with view-only access, where nobody can edit anything
- Reports shared with personalised visuals or data exploration turned on
- Self-service BI, where users build their own semantic models or reports on your lakehouse
That last one is where it matters most. When users build their own models on your lakehouse, they need to know which tables are dimensions and which are facts. I still prefer to give them documentation and descriptions, and to leave Dim and Fact out of the table names.
So in the presentation layer, underscores and prefixes come off:
- Semantic model:
DNA Sales MI - Tables:
Product,Sales,Customer - Columns:
Product ID,Product Name,Sale Date Time
I use Semantic Link Labs to do the renaming rather than doing it by hand, and I've since written about how to rename a published model safely, which is the harder version of this problem.
Closing thoughts
Naming conventions are a small part of a data solution and they're still the part that makes everything else legible. A good name does one job: whether you're looking at a workspace, a Git diff, a capacity metrics table or a failed run in monitoring, it should tell you what the thing is and where it sits without you having to open it.
The version of this I'd argue with myself about is how much to encode. Every segment you add is one more thing someone has to keep right, and I'd rather a team followed a looser convention than quietly abandoned a strict one. If you take one thing from the tables above, make it the type codes. Layer, domain and environment are all worth dropping if your workspace structure already carries them.
Johnny's post on naming your Fabric artifacts is still a good read alongside this one.
Last time I said I hadn't covered every item in Fabric. Now I have, or close to it. The few gaps left are places where Microsoft hasn't published the detail yet, and I've flagged those inline instead of guessing. Let me know what you're using in your own developments, especially if you've solved the connection naming problem more neatly than I have.
Happy naming :)