Power Platform Connectors Versioning and Change Management

November 15, 2023
25 min read

This sixth installment of the “Power Platform Custom Connectors A to Z” series delves into some of the more nuanced aspects of the connector life cycle, building upon the advanced concepts introduced in part five. While the prior segment covered topics such as optional configuration settings, dynamic schemas, and the use of custom code, the present focus shifts to the equally important post-creation stages. It addresses the available mechanisms for deploying connectors to makers across multiple environments, along with strategies for their subsequent maintenance, including updates, corrections, and revisions. It also emphasizes the significance of robust version control, effective change management, and the systematic tracking of revisions to safeguard against potential disruptions and ensure operational continuity.

For reference, the series outline is as follows:

  1. Introduction and Overview
  2. Connector Fundamentals
  3. Basic Building Blocks: Security, Actions, Requests, and Responses 
  4. Advanced Capabilities: Triggers, References, and Policies
  5. Finishing Touches: Customization and Extensibility
  6. Staying In Control: Versioning and Change Management (this article)
  7. The Big Picture: Performance, Hosting, and Scalability
  8. Making It Official: Publishing, Certification, and Deployment
  9. Going All In: Commercialization and Monetization
  10. Lessons Learned: Tips, Tricks, and Advanced Techniques

Solutions

Packaging various components together, such as a data table, flow, and custom connector, and deploying them as a single unit is accomplished in Power Platform using solutions. In this context, a solution is a grouping of individual components that are created and configured in a development environment, then combined into a single unit for deployment into other environments. There are two types of solutions: unmanaged and managed. Unmanaged solutions contain the raw, editable elements that will be packaged together for export in an editable state for further modification in another environment, whereas a managed package contains elements that cannot be modified after being exported.

The following conceptual diagram illustrates the solution export/import process.

A logical diagram illustrating the unmanaged to managed pipeline for Power Platform solutions.
Figure 1: The development to production pipeline for Power Platform solutions. | Copyright © Microsoft 2023 | https://learn.microsoft.com/en-us/power-platform/alm/solution-concepts-alm

There are various elements to consider when creating a solution. Due to size limit restrictions (32 MB maximum total package size), creators must first determine what components should go into the package. Apps and flows can both grow quite large, and when combined with a custom connector definition, code file, and other related assets—each of which consumes a potentially significant amount of storage—creators may need to split solutions along logical boundaries to avoid exceeding the total size limit. Solutions can have dependencies on other solutions, so a common practice is to create multiple solutions based on the dependency hierarchy, which also helps to address the size restrictions. Within a solution, there may also be dependencies between individual components, so packages should be designed in a manner that satisfies these types of inter-component dependencies.

It is entirely feasible to release a solution package comprised of nothing but custom connectors. Unmanaged solutions can have dependencies on managed solutions, making it possible for one creator to be responsible for connector packaging and deployment, while another creates packages with functional elements like forms and flows that depend upon the connector-only package. These are known as layered solutions; creators have a great deal of flexibility in organizing layers as they see fit, provided they follow a general structural model similar to the following.

A logical diagram illustrating how managed and unmanaged layers can be combined within a solution.
Figure 2: Managed and unmanaged layers in a solution. | Copyright © Microsoft 2023 | https://learn.microsoft.com/en-us/power-platform/alm/solution-layers-alm

There are some limitations that creators should be aware of when including custom connectors in a solution. To begin with, connectors must be imported before any flows or connection references that rely upon them. Referring back to the layers model, this means that connectors should be part of any base solutions at the lowest layer, effectively treating them as core dependencies for the solution stack. From a practical perspective, this entails breaking apart dependent and functional solutions, such that a complete package would contain a connector solution that is imported first, followed by any flow or app solutions, including connection references.

This may seem counter intuitive, as connection references would seem to be logically grouped with the connectors they are associated with. However, since there is no mechanism within the solution framework that allows creators to define a specific activation order, and a connector must be registered before a connection reference, this dictates the use of two separate solutions to guarantee the proper registration sequence. (Although it is possible that a single solution containing connectors, connector references, and flows may import properly on occasion, it is very likely to fail at some point, especially when there are multiple instances of each component type within the package.)

Another consideration relates to connector security. By default, connectors in a solution are created without role assignments, as these are not exportable across environments. Even when role assignments are applied post-creation, they do not persist across export/import operations because they rely upon specific user objects within each environment. Due to this limitation, when a connector solution is imported, the administrator must manually make any required role assignments in each environment. More information on security roles and privileges within Power Platform can be found at https://learn.microsoft.com/en-us/power-platform/admin/security-roles-privileges.

Finally, and perhaps most importantly for first-time solution builders, custom connectors created outside of the solution framework cannot be added to a solution. In most cases, this is easily overcome by creating a new connector from within the solution (New > Automations > Custom Connector), copy/pasting the definition from the Swagger view, and saving the connector; however, there may be additional overhead involved if there are policy templates, code files, custom images, and other elements associated with the connector, requiring some back and forth between wizard instances. Be advised that following this process currently causes the designer UI to launch a new tab with the familiar left navigation menu from the maker experience. When the connector is saved, however, returning to the original tab and selecting Done will refresh the solution package contents and show the new connector. It is a bit confusing at first, made all the worse by how which it mimics the non-solution connector creation navigation and shifts focus away from the solution management views. After a few practice runs switching back and forth between the creation wizard and the solution designer, however, it begins to make a bit more sense.

A screen capture of the Solution contents view after selecting New > Automations > Custom Connector.
Figure 3: Solution contents view during connector creation. | Used with permission from Microsoft.

Connector updates are controlled through the solution versioning processes. Modifications to connector behavior or functionality are made in the original unmanaged solution and then imported as a new managed solution version. Upon import, the administrator has a choice to Upgrade the existing managed package to the new version, deleting any removed components in the process; Stage for upgrade, which upgrades without deleting any missing artifacts; or Update, a simple replacement of the old solution with the new one. There are also Clone a patch and Clone a solution options for applying solution updates, but these are more involved and come with additional restrictions. More information on how to use these options is available at https://learn.microsoft.com/en-us/power-platform/alm/update-solutions-alm.

There is a lot more to the solution creation and management process, but a complete discussion of all the decision points is beyond the scope of this series. For more information about solutions, including advanced topics like managed properties, segmenting, updating, and organizing, visit https://learn.microsoft.com/en-us/power-platform/alm/solution-concepts-alm.

Versioning

The more actions a connector has, and the longer that connector is in use, the greater the likelihood that something will change at some point. Perhaps the API provider decides to change the name or data type of an input parameter, or the basePath is renamed to eliminate ambiguity between services. Whatever the case, when things change, the connector creator must decide how those changes are going to be reflected in the underlying definition and exposed to users.

There are essentially two types of changes: those that affect the connector as a whole (global) and those that only affect specific actions (localized). These are dealt with in two entirely different ways within the definition. They are also approached differently in terms of the overall deployment process.

Global Versioning

Global changes affect those portions of a definition that reside at a root level, such as info, tags, security, and schemes. None of these elements offers any type of in-place version management—that is, the ability to simultaneously have two or more slightly different instances of the same object within a single definition. When a property or value within a global element is changed, like the host URL or authentication method, it affects the entire connector. If such changes are deployed into an existing environment where previous versions of a connector are running, they could break running apps and workflows. That is a troubling scenario, which could have far-reaching consequences across multiple tenant environments, and not one that any cloud platform provider wants to encourage.

To mitigate global connector updates from introducing breaking changes, Power Platform performs a bit of silent versioning behind the scenes. Any running apps or flows continue to use the connector version that existed when they were published. For them to recognize connector updates, each flow or app must be edited and republished. This can be time consuming for makers, but it places much-needed safety rails around production workloads. The downsides to such system-controlled versioning are that it occurs beyond the creator’s control and results in multiple versions of a connector running at the same time.

By way of example, consider the sample Asteroid NeoWS connector from previous articles. Assume that Flow A is using this connector. A message is received from the API provider that the URL is changing from https://api.nasa.gov/neo/rest to https://api.nasa.gov/neo/graph on the first day of the coming month. The connector definition must now be modified accordingly, replacing the basePath value of /neo/rest with /new/graph. After making this change and updating the connector, a new test flow is created on the date of the changeover, and it works successfully. Notifications are received stating that Flow A is failing, since it continues to use the old /neo/rest basePath value from the original version of the connector. To rectify this situation, it is necessary to edit Flow A and republish it. (In some cases, it may be necessary to manually re-create at least one action in the flow to force the changes to be recognized by the Flow designer interface.) Likewise, Canvas App A that uses the same connector must also be edited and republished. The more apps and flows that share actions from the same connector, the more edit and republish tasks are required.

Localized Versioning

Changes can also be implemented at the action level. Unlike global changes, there is a method for applying in-place localized versioning, assuming that the API provider supports it. This is achieved by modifying the path value with a version qualifier, such as “/v2”, or adding a query string parameter. Another, less popular, method is to specify the version in a custom header value (which could be done without modifying the connector definition by using a policy template).

The path-based method is the one that API providers use most often, thus the prevalence of “/vSomething” in many endpoint URLs. This method was also employed in the sample Asteroid connector mentioned earlier. By starting with a path of /v1/feed, the definition is preconfigured to facilitate an alternate path of /v2/feed in the future. Even if the /v1 prefix had been left off, a new /v2 prefix could be added to a subsequent action at any point in time, providing two versions of the action that the creator can choose from.

It should be noted that this path-based choice can lead to some confusion. Due to the fact that there is so little screen real estate available in the designer to display information about actions and their parameters, it can become difficult for creators to determine which one they should use in a flow or app. Anyone who has tried to send an email from Power Automate has experienced this issue, since there are multiple versions from different connector publishers to choose from that all do essentially the same thing. (The default Microsoft connector alone has three different versions.)

A screen capture from the Power Automate Flow designer showing the various options available for sending an email.
Figure 4: Options for sending an email from Power Automate. | Used with permission from Microsoft.

Despite the potential for confusion, the path-based versioning approach for actions remains one of the best options for managing action changes. For the same reason that global changes cannot be immediately propagated without breaking running apps and flows—action changes, including any sub-elements like parameters, outputs, operation IDs, and even tags—can introduce undesired behaviors. The system-level versioning that occurs behind the scenes does provide a certain level of automatic protection by tethering each app or flow to the connector version that existed when it was published; however, with localized in-place version management, the maker has a visually obvious choice of which action to use.

Returning to the Asteroid connector example, a new version of the feed endpoint is introduced that contains an additional input parameter named type on the path /v2/feed. This new option permits additional data filtering, allowing the maker to select the specific kind of asteroid events to return in the result set. There will now be two different endpoints available to creators that use this connector:

"/v1/feed": {
     "get": {
       "description": "Retrieve a list of Asteroids based on their closest approach date to Earth",
       "summary": "Approaching asteroids",
       "operationId": "Feed",
       "tags": [ "NEO" ],
       "parameters": [
          {
           "name": "start_date",
           "in": "query",
           "required": false,
           "type": "string",
           "x-ms-summary":"Start Date",
           "x-ms-visibility": "important"
          },
          {
           "name": "end_date",
           "in": "query",
           "required": false,
           "type": "string",
           "x-ms-summary": "End Date",
           "x-ms-visibility": "advanced"
          }
        ],
       "responses": {
         "200": {
           "description": "default",
           "schema": {
             "$ref": "#/definitions/asteroidInfo"
            }
          },
         "400": {
           "description": "Error",
           "schema": {
               "$ref": "#/definitions/errorMessage"
            }
          }
        }
      }
    },
   "/v2/feed": {
     "get": {
       "description": "Retrieve a list of Asteroids by type based on their closest approach date to Earth",
       "summary": "Approaching asteroids (V2)",
       "operationId": "FeedV2",
       "tags": [ "NEO" ],
       "parameters": [
          {
           "name": "start_date",
           "in": "query",
           "required": false,
           "type": "string",
           "x-ms-summary":"Start Date",
           "x-ms-visibility": "important"
          },
          {
           "name": "end_date",
           "in": "query",
           "required": false,
           "type": "string",
           "x-ms-summary": "End Date",
           "x-ms-visibility": "advanced"
          },
          {
           "name": "type",
           "in": "query",
           "required": false,
           "type": "string",
           "x-ms-summary": "Asteroid Type",
           "x-ms-visibility": "advanced"
          }
        ],
       "responses": {
         "200": {
           "description": "default",
           "schema": {
             "$ref": "#/definitions/asteroidInfo"
            }
          },
         "400": {
           "description": "Error",
           "schema": {
               "$ref": "#/definitions/errorMessage"
            }
          }
        }
      }
    },

Since both the /v1 and /v2 endpoints exist side by side in the definition, no breaking changes are introduced when the connector is updated. Apps and flows that use /v1 will continue to use it without any issues as long as it remains supported by the remote system, whereas new instances can use either /v1 or /v2 at the maker’s discretion. If an existing app or flow needs the /v2 action for any reason, the maker can edit it, add the new action (the latest version of the connector is always displayed, not the original tethered version), and then delete the original action and republish.

It is a good practice to include version qualifiers in each path value from the beginning, even if there are no plans to add versions in the future. The decision whether to place the qualifier before or after the endpoint is up to the API provider. Creators who also control the backend API structure should avoid putting version qualifiers in the global basePath value because this would preclude clean, path-based, localized versioning. An endpoint URL that contains multiple concurrent version qualifiers, such as https://api.nasa.gov/neo/rest/v1/v2/feed, can be difficult to interpret. In cases where requirements dictate version control at both the global basePath and individual path level, the following pattern may be more effective: https://api.nasa.gov/neo/v1/rest/v1/feed or even https://api.nasa.gov/neo/v1/rest/feed/v2. These situations present a good opportunity to combine path-based versioning with query-based versioning, with a resulting URL like this: https://api.nasa.gov/neo/rest/v1/feed?apiVersion=1 (The individual path must still contain a version qualifier because duplicate path names are not allowed within a definition, even if they have different query parameters.)

Annotation

There is one additional version-related setting specific to Power Platform connectors that is not included in the reference OpenAPI Specification. The x-ms-api-annotation custom property defines the status of a connector as either preview or production. When used with operations (verbs), this property object has three additional sub-properties:

  • Family: Name that applies to every revision of the operation. Used to indicate related operations, combined with revision number to indicate matching levels across operations. Default value is operationId.
  • revision: Revision number (whole integer) of the specified operational family.
  • expires: Indicates end of support or end of life.

As the name implies, these are only annotations. They have no impact on the functionality of a connector or any of its actions. Although the official Microsoft documentation about connector versioning at https://learn.microsoft.com/en-us/connectors/custom-connectors/operational-versioning includes metrics regarding Preview and Production status, these are only guidelines; actual parameters for a change in status are subjective and at the discretion of the connector creator. Perhaps in the future these annotations will have deeper integration that influences connector behavior. For the moment, however, creators can use them to better organize their actions and provide additional context around operational status for individual actions.

Updates and Modifications

Generally, updates and modifications to a connector require editing all apps and flows that use the connector and republishing them. This includes localized modifications to existing objects, regardless of whether versioning is in place. Changing key definition elements like parameter names, data types, security settings, response objects, schemas, and operation IDs are all breaking changes that can cause published solutions to fail. The built-in tethering mechanism prevents such breakages, requiring manual reconfiguration and republishing for each affected app or flow.

Having established that actions must be reconfigured to take advantage of new capabilities, one of the primary questions regarding connector updates is: What elements within a definition can be changed without requiring reconfiguration? As you might expect, modifications that meet this criterion are mostly cosmetic in nature, but some can be structural as long as they are additive instead of reductive. For example, new securityDefinitions objects can be introduced at the global level but no existing definitions can be removed. (As long as the existing connection matches one of the defined security definitions, the creator should not have to establish a new connection.)

The following table provides an overview of some supported changes, indicating whether the value can be changed without requiring reconfiguration:

Definition Element Global Action
title Yes --
description Yes Yes
summary -- Yes
version Yes --
host No --
basePath No --
schemes No --
consumes (additive only) Yes Yes
produces (additive only) Yes Yes
tags Yes Yes
securityDefinitions (additive only) Yes --
Security (additive only) Yes Yes
path (additive only; use versioning) -- Yes
verb (additive only) -- Yes
operationId -- No
parameter name -- No
parameter type -- No
parameter description -- Yes
parameter required -- No
parameter x-ms-summary -- Yes
parameter x-ms-visibility -- Yes
parameter value-path -- No
parameter value-title -- No
parameter schema $ref -- No
parameter responses (additive only) -- Yes
parameter examples -- Yes
property x-ms-api-annotation Yes Yes

Table 1: Comparison of permissible connector definition changes by scope.

Deprecation

When multiple versions of an action exist within a definition file, creators may benefit from additional guidance on which versions are still actively supported and which are on the path to retirement. One way in which this intent can be communicated within the definition file is by marking operations with the deprecated property. When set to true (the default is false, which is assumed if the property is omitted), it indicates that the operation can still be used but should be avoided in favor of newer versions.

In the sample Asteroids connector, it is unclear which version of the /feed action is preferred. Adding the deprecated tag to /v1/feed is meant to provide helpful guidance to the creator at design time, indicating that the /v2/feed version should be selected:

"/v1/feed": {
     "get": {
       "deprecated": true,
       "description": "Retrieve a list of Asteroids based on their closest approach date to Earth",
       "summary": "Approaching asteroids",
       "operationId": "Feed",
       "tags": [ "NEO" ],
       "parameters": [
          {
           "name": "start_date",
           "in": "query",
           "required": false,
           "type": "string",
           "x-ms-summary":"Start Date",
           "x-ms-visibility": "important"
          },
          {
           "name": "end_date",
           "in": "query",
           "required": false,
           "type": "string",
           "x-ms-summary": "End Date",
           "x-ms-visibility": "advanced"
          }
        ],
       "responses": {
         "200": {
           "description": "default",
           "schema": {
             "$ref": "#/definitions/asteroidInfo"
            }
          },
         "400": {
           "description": "Error",
           "schema": {
               "$ref": "#/definitions/errorMessage"
            }
          }
        }
      }
    },

The custom connector creation wizard provides visual confirmation of deprecated actions by striking through the name and disabling the operation in the test utility.

Screen capture of the connector creation wizard showing a deprecated action struck through and disabled in the test utility user interface.
Figure 5: A disabled action in the creation wizard. | Used with permission from Microsoft.

Unfortunately, the flow designer UI does not yet display any indicator that an action has been deprecated. Assuming that such functionality is added in the future, marking end-of-life operations with the deprecated property is a good practice to adopt, as soon as it becomes necessary to begin versioning actions. In the interim, adding text to the operation name or description can be an effective substitute for proper deprecation handling in the action selector.

Screen capture of the flow design action selector demonstrating how it fails to notify the creator about the deprecation status of an action.
Figure 6: The flow designer fails to display a message to the creator based upon the deprecated property value.  | Used with permission from Microsoft.

Source Control

As connector definitions evolve, it can be useful (and sometimes necessary) to maintain copies of each individual version throughout the connector life cycle. This is especially true when multiple creators are collaborating on large definitions. The larger and more complex a definition becomes, and the more iterations it goes through, the harder it is to track who did what, when, and why. Maintaining an accurate record of each change can be critical when troubleshooting problems or rolling back breaking changes.

Professional developers use source control tools expressly designed for this purpose. In fact, managing source control is one of the primary tasks that programming teams engage in daily. There are numerous source control systems available, many of which are free and open source. Microsoft provides two such systems in Azure DevOps, which is geared towards traditional enterprise developers who rely upon features designed for structured team collaboration, and GitHub, which has more of an open-source and community contributor focus.

Regardless of which system is used, adding connector definitions to source control, along with the supporting settings and code files that can be retrieved using the paconn utility, is a best practice that all creators should engage in. It can save countless hours of rework and prevent excessive downtime by enabling immediate rollbacks to known working versions. In fact, Microsoft requires that all certified and independent connector publishers submit their source files to the public Power Platform Connectors GitHub repository at https://github.com/microsoft/PowerPlatformConnectors before they will accept a connector for inclusion in the official gallery. Adopting a pro dev mindset for source management may seem like unnecessary overhead for connectors that are comprised of just a few basic text files, but the benefits far outweigh the time spent setting up, learning, and actively using a good source control system.

Conclusion

After successfully creating a custom connector, the next task is to effectively manage that connector throughout its life cycle. Solutions provide a packaging and deployment mechanism that can be used to distribute connectors, control connector dependencies, and keep them updated wherever they have been deployed. Versioning within a connector definition gives creators a method for introducing new capabilities or changing existing behaviors, both at the global and individual action level. Although some connector elements can be safely changed and redeployed without impacting core functionality, others require connector actions to be reconfigured and their parent apps or flows republished. Actions can also be deprecated, making it obvious which ones should and should not be used when multiple versions exist. Regardless of which methods are used for connector updates and modifications, a good source control system is essential for effective change management.

This concludes the deep dive into the creation and management of custom connectors but there is plenty of ground left to cover. In part seven, the focus moves from the front end to the back end, covering important topics for creators who are also responsible for the API operations that their connectors target. These include guidelines for optimal performance, the key elements associated with hosting a production API infrastructure, and techniques for scaling to accommodate large, distributed workloads. Subsequent articles in the series will discuss the publishing and certification process for creators who wish to distribute their connectors to a global audience, the ins and outs of connector licensing and monetization, and conclude with some real-world advice on how to avoid common mistakes, leverage automation for better connector management, and even provide some things to consider when operating a multi-cloud connector infrastructure.

Eric Shupps

Eric Shupps

Eric Shupps is the founder and CTO of Apptigent, a leading provider of cloud-based software solutions for Microsoft, Salesforce, and more. Eric has worked in the industry for more than 30 years, primarily focused on Microsoft software and services, as a consultant, administrator, architect, developer and trainer. He co-hosts the Community CloudCast, has authored numerous technology articles, and speaks at user group meetings and conferences around the world.