What it does
Customer Service sits on Dataverse, so it inherits Power Platform ALM: solutions, layers, publishers and environments. The wrinkle is that a large share of service configuration is data rather than metadata, so a clean solution pipeline still leaves you moving records by hand.
Key facts
- Managed solutions everywhere except development. An unmanaged layer sits above every managed layer and wins, which is why direct edits in production quietly override everything you ship afterwards.
- Use one custom publisher with one meaningful prefix. Components can't be moved between solutions with different publishers without deletion and recreation or holding-solution tricks.
- The number of development environments is driven by how many versions you need in flight at once, not by team size. One live version plus one in development is two dev environments; add a regional variant and you're at four.
- Configuration and reference data move with the Configuration Migration Tool; Package Deployer handles a bundle of solutions plus files and code.
- Environment variables and connection references exist so environment-specific values stop being hard-coded. Use them.
- On the service side, session templates, notification templates, application tab templates, agent scripts, macros, workstreams, intake rules and the routing configuration tables are solution-aware.
- Not solution-aware, and needing the Configuration Migration Tool: skill-based routing configuration (characteristic, rating model, rating value), capacity profiles, and record queues with their assignment configuration, operating hours and overflow actions.
- Some things can't be migrated at all and have to be recreated in the target: calendar items on operating hours records, and the bookable resource characteristic type global option set value if skills are in use.
- Migration order matters for routing configuration, and Microsoft documents a specific sequence. Importing queues before their decision contracts fails.
- Configuration Migration Tool exports of routing data carry source-environment GUIDs for decision contracts that must be replaced in data.xml before import.
- Queue imports can't mix creates and updates in one run, and the queue type column has to be present in schema.xml for creates and removed for updates.
- Tooling: Solution Packager for source control, Power Platform Build Tools or GitHub Actions for the pipeline, Power Apps Checker for static analysis.
When to use / skip
There's no skip. Every Customer Service project needs a defined pipeline, even the small ones — particularly the small ones, because they're the projects where someone configures a workstream directly in production on a Friday.
The judgment is how much you automate. A single-solution deployment with one dev environment and a manual export-import through UAT is entirely defensible for a fifty-agent service desk. A client with parallel workstreams, several teams and a regulated change process needs source control and a build pipeline, and the cost of that is real.
What you should never do is skip the configuration data half. Teams build a beautiful automated solution pipeline and then discover on go-live weekend that none of the queues, skills or capacity profiles came with it.
Configuration decisions
- One solution or several, and if several, what the dependency order is. Splitting later is much harder than splitting early.
- Publisher and prefix, agreed with the client and fixed for good.
- How many environments, of which types, and who can deploy to each.
- Which service configuration is treated as code (in a solution) and which as data (Configuration Migration Tool schemas), with a documented order of operations.
- Whether unmanaged customisation in production is permitted at all, and how you detect it if it isn't.
- What "go-live weekend" actually consists of, step by step, including the manual recreation items that no tool covers.
Gotchas
- Routing and channel configuration is the part that catches people. Solution import succeeds, the environment looks right, and the queues are empty because they were never in the solution.
- Decision contract GUIDs differ per environment. An import that appears to succeed can leave rulesets pointing at nothing, and the failure surfaces later as work not routing.
- Calendar items on operating hours are recreated by hand in every environment, every time. Build it into the runbook or it gets missed.
- Unmanaged customisations made in production during hypercare are invisible until the next managed import doesn't take effect. Then you're debugging layers.
- Copying a Customer Service environment for testing brings the channel configuration with it, including live endpoints. Sanitise before anyone touches it.
- Solutions carry security roles but not role assignments, and carry table auditing settings that a careless import can flip.
- Different publishers across two consultancies working on the same client is the gift that keeps giving. Check before you write a line.
Consultant notes
- Write the deployment runbook during the first migration to UAT, not the week before go-live. The manual steps are only discoverable by doing it.
- Rehearse the routing configuration migration at least twice. It's the step with the most ordering constraints and the least helpful errors.
- Tell the client early that some service configuration will be recreated by hand in each environment. It sounds like a shortcoming, and it's better heard in design than at cutover.
- Lock down production customisation rights before go-live and mean it. Every hypercare exception becomes permanent.
- Check the publisher prefix on anything you inherit. Fixing it costs days; noticing it costs minutes.
Worth another look as more service configuration becomes solution-aware — the list has been growing wave by wave.