Migrate Slack integrations to Mattermost without losing the workflows behind them
Most Slack exits start with a renewal, a data residency requirement or a lock-in concern, and the workspace they leave behind is full of bots, slash commands and incoming webhooks that someone depends on every day. The key point to plan around is that message history moves through Mattermost's documented import path, while integrations do not. The Slack migration tooling converts users, channels, direct messages, threads and attachments, but apps, webhooks and custom emoji images stay behind. Every integration therefore becomes a separate rebuild with its own owner, test and cutover step.
The work usually falls to the platform or IT team, working with the people who own each app or script. Start by inventorying every Slack app, slash command, outgoing and incoming webhook and scheduled job, and record who owns it, which channels it posts into and what systems it calls. Incoming webhooks are the cheapest to move. Mattermost accepts Slack-style payloads, including the payload= prefix when no Content-Type header is sent and the icon_emoji parameter from v5.14, and it translates <url|text> links and <!channel>, <!here> and <!all> mentions. Test each sender against a staging Mattermost server before changing its URL.
The risk sits in what does not translate. Mattermost's incoming webhooks do not support mrkdwn, parse or link_names, <!everyone> and <!group> mentions, <#CHANNEL_ID> channel links or single-asterisk *bold* formatting. Messages that depend on these will render incorrectly or silently lose their mentions, so search each payload template for them and rewrite the affected text. Slash commands and bots need a fresh Mattermost integration and a new endpoint, so they are a development task rather than a configuration change. Confirm with your own developers which Mattermost API features your bots need, and plan an overlap period where the Slack app and its Mattermost replacement both run in a test channel.
For cutover, keep a written register of every integration with its owner, its replacement, its test result and its rollback path. Confirm the Mattermost version you will deploy against the current Mattermost server releases page, since support windows determine when you must upgrade again. The effort depends mostly on how many custom bots exist and how much of their output depends on Slack-specific formatting, so ask your implementation partner to size the inventory first and quote the rebuild from that written scope.
Which Slack integration pieces map to Mattermost and how clean each move is
This table compares each Slack integration piece with its Mattermost equivalent and rates the move as clean, needing rework, or a gap. Read it as an inventory checklist: anything marked clean can usually be reused as written, anything needing rework must be edited before cutover, and anything marked gap must be rebuilt or replaced by a different mechanism.
| Slack capability | Mattermost equivalent | Migration note |
|---|---|---|
| Incoming webhooks | Incoming webhooks accepting Slack-style payloads | Clean for basic payloads. Requests without a Content-Type header take the payload= prefix; test each sender after cutover. |
| Outgoing webhooks | Outgoing webhooks configured per team | Needs rework. Recreate each one, point it at the new URL and confirm the trigger words and callback settings in your own environment. |
| Slash commands | Custom slash commands on a team | Needs rework. Recreate each command and its endpoint; the command name and response handling must be confirmed against your Slack inventory. |
| Bots and apps | Bot accounts and integrations built against the Mattermost API | Gap for installed Slack apps. Slack app installations do not migrate, so each bot needs a rebuild or a replacement from its owner. |
| Mention and link formatting | Slack-style <url|text> links and <!channel>, <!here>, <!all> mentions | Needs rework. Remove mrkdwn, parse and link_names parameters, <!everyone>, <!group>, <#CHANNEL_ID> links and single-asterisk bold. |
| Custom emoji | Custom emoji on the Mattermost server | Gap for images. Slack custom emoji images do not move in the import, so re-upload each one the teams still use. |
| User groups | Channel membership and team membership settings | Gap. User groups do not migrate, so rebuild group targeting by hand or through your own automation. |
| Slack Connect channels | No direct equivalent in Mattermost | Gap. Shared channels with outside organizations do not come across; plan a separate arrangement such as guest accounts with a security review. |
What the Slack export carries and what you must rebuild by hand
A Slack export is the starting point for moving people and history, but it does not carry the apps, webhooks and bots that teams depend on. The cards below cover what the export plan allows, how the Mattermost import path works, what falls out during conversion, and how to inventory the integrations you must recreate before cutover.
Export plan sets the scope
Every Slack plan can export public channels, but private channels and direct messages need a Business+ or Enterprise plan. Custom exports by member or conversation are limited to Enterprise. Confirm which plan your workspace is on before you plan the cutover, because a Free or Pro export will be missing private conversations that your teams may expect to see in Mattermost. Request the export early so the approval step does not hold up the project.
mmetl converts, mmctl loads
Mattermost moves a Slack export in two steps. The mmetl tool converts the Slack export into Mattermost's bulk import format, and mmctl loads that file into the server. Run the conversion against a copy of the export and review the output before loading it into production. Users, channels, direct messages, threads and attachments are carried across, so the import validates the people and history side of the move, not the automation side.
Integrations do not migrate
The import does not carry Slack integrations, so every app installed in the workspace stops working on the day you cut over. Build a list of each installed app, its owner, the channels it posts to and the events it reacts to. Treat that list as the acceptance checklist for the cutover, and assign an owner to each item so that no integration goes unassigned. Expect the list to be longer than the apps page in Slack shows, because custom internal integrations often sit outside it.
Custom emoji and user groups
Custom emoji images and Slack user groups are not part of the Mattermost import. Export the emoji files separately and re-upload them, or confirm with the business owner which ones still matter. User groups used for mentions or permissions need to be recreated as Mattermost groups, and any workflow that depends on a group name will break until it is mapped. Record which groups drive notifications, approvals or channel access so they can be rebuilt in the same change window.
Slack Connect channels
Slack Connect channels shared with customers, partners or vendors do not migrate. Each external shared channel needs a decision: archive it, move the conversation to a channel your organization controls, or set up guest access in Mattermost with an agreed security review. Identify these channels from the workspace admin view before the export, since the external members and their data sit outside the import scope.
Inventory webhooks, commands and bot tokens
Make a register of every incoming webhook URL, slash command and bot token that Slack issued. Each webhook URL points to a Slack endpoint that stops receiving messages after cutover, so the producing system must be updated to a Mattermost incoming webhook URL. Slash commands and bot tokens need new definitions and credentials on the Mattermost side. Store the new secrets in your secrets manager, rotate the old Slack tokens, and test each producer against a staging channel before the production switch.
How to inventory, pilot and cut over Slack integrations in Mattermost
This sequence rebuilds Slack's apps, webhooks and bots on Mattermost in a controlled order, so each integration is inventoried, tested and retired only after its replacement has been proven. The output at each stage is a record you can review before cutover.
Inventory every app, webhook, command and bot
Start by listing everything that touches the Slack workspace: installed apps, incoming and outgoing webhooks, slash commands, workflow steps and bot users. For each item, record the owner, the channels it posts to, the trigger, the payload format and any mention or link syntax it uses. Ask workspace admins for the app directory and the integration logs, because a Slack export does not carry these items. The output is an inventory register with one row per integration and a named owner who confirms it. The register is done when the owners have signed off every row, including the ones they expected to be retired.
Classify each integration by payload and dependency
Group the register into three bands: webhooks that send plain text, webhooks that use Slack-only fields or formatting, and integrations that depend on Slack's own APIs, interactive buttons or modals. Mark the payload features each webhook uses, such as mrkdwn, link_names, parse or the <!everyone> and <!group> mentions. This classification tells you which items convert with little work and which need a rebuild. The output is a classified register that the team reviews with the owners. Confirm each feature against Mattermost's incoming webhook documentation rather than from memory.
Pilot the conversion with mmetl on a sample export
Export a representative set of public channels from Slack, then run mmetl against that sample to produce Mattermost's bulk import file. Load it into a non-production Mattermost server with mmctl and check that users, channels and attachments arrive as expected. Note that integrations do not migrate, so the pilot confirms your data path, not your bots. The output is a pilot log that records each command, any conversion warnings and the import result. Use the same Mattermost version you plan to run in production, and confirm the export plan you hold permits the channels you are testing.
Rebuild and test each webhook against Mattermost rules
Create each incoming webhook in Mattermost on a test channel and point the sending system at it. Send the payload in the form each integration uses, check that the Slack-style links and channel, here and all mentions are translated, and replace any unsupported mrkdwn, parse, link_names, group or channel-ID syntax with forms Mattermost accepts. Where a request has no Content-Type header, confirm whether the payload= prefix is needed. Record the request, the rendered message and the outcome in a test log. The step is complete when every webhook has a passing entry and each rebuilt item is marked in the register.
Re-create slash commands and bots with owners
Rebuild each slash command and bot as a Mattermost integration or a separately hosted service that the owner maintains. Slash commands and bots are not carried over by the migration, so each needs its own endpoint, token handling and permissions, and each should be reviewed against your identity and access rules. Run a test plan with real users in a pilot team, covering normal and failure cases. The output is a signed test record per command or bot and a list of any features that were dropped and accepted by the business owner.
Run a parallel period with both platforms posting
For a defined period, keep the Slack integrations live and send the same notifications to matching Mattermost channels. Compare delivery, formatting and timing for each integration, and log any mismatch in a shared defect list. Check that people reading the Mattermost channels receive the same information and that no message is lost or duplicated. The output is a parallel-run report that shows each integration's match rate and the defects still open. Agree the length of the parallel period with the owners in writing before it starts.
Cut over and decommission Slack webhooks
When the parallel report shows no open blocking defects and owners have approved, switch each sending system's endpoint from Slack to Mattermost and disable the Slack webhook. Revoke the Slack app tokens and remove the app from the workspace once its traffic has stopped. Keep the Slack export and the inventory register as an archive for the agreed retention period. The output is a cutover record listing each integration, the switch time, the revoked credential and the owner who signed it off.
Which Slack-style webhook payloads work unchanged in Mattermost
Most simple Slack-style incoming webhooks work in Mattermost without code changes, but only if the request is sent the way Mattermost expects. A request without a Content-Type header is read with the payload= prefix that Slack uses, so an existing sender that posts a URL-encoded JSON body keeps working. The icon_emoji parameter is supported from v5.14, so any integration relying on it is covered on current servers. Slack-style <url|text> links and the <!channel>, <!here> and <!all> mentions are translated on arrival. Senders that set a JSON Content-Type header are parsed as native Mattermost payloads, so the sender's header matters as much as its body.
The fields and forms that do not carry over fail quietly, which is why a message can post and still be wrong. Mattermost's incoming webhooks do not support Slack's mrkdwn, parse or link_names parameters, so a sender that depends on them loses its formatting or mention behavior without an error. The <!everyone> and <!group> mentions are not translated, and <#CHANNEL_ID> channel links are not rendered. Single-asterisk *bold* text is Slack's syntax and does not render as bold in Mattermost, where double asterisks are used. Each of these needs an edit in the sender, a change to the message template, or a decision to drop the feature.
Run a payload test for every integration before cutover, using a test channel and a copy of each real payload. Inventory the senders, record the exact fields and mention forms each one uses, then post the payload to a test webhook and compare the rendered result with what users see in Slack. Confirm the sender's Content-Type header, check that mentions notify the intended people, and check links and bold text. Treat a message that posts without error as unverified until a person has read it in the rendered channel. Keep the results in a short register so the platform team can show which integrations were changed and which were retired.
How the integration rebuild differs by Slack footprint
A small team with a handful of incoming webhooks usually has the lightest rebuild. Most of these are one-way notifications from monitoring, CI or a form tool that post a message into a channel. Mattermost accepts Slack-style payloads on its incoming webhooks, so many of these posts can keep their existing body once the webhook URL is replaced. The work is mostly inventory and verification rather than code.
- Inventory the URLs: List every webhook in Slack, the channel it posts to, and the system that owns the sending code. Each one needs a new Mattermost webhook and a configuration change on the sender.
- Check the payload format: Requests without a Content-Type header take the
payload=prefix for Slack compatibility, so confirm which senders send that way and which send JSON. - Review formatting: Replace any *bold* single-asterisk text and any
<!everyone>or<!group>mentions, since these are not supported on Mattermost incoming webhooks. - Test one message per channel: Post a test from each sender and confirm the text, links and mentions render as expected.
Before cutover, confirm with each owner that their sender can change its webhook URL without a release, and keep the old Slack URL active until every test message lands.
A team with custom slash commands and bots faces a different problem. Slash commands and bots run code that calls Slack APIs, handles user input and often stores state. Mattermost does not import these from a Slack export, so each one must be rebuilt, reconfigured and tested against Mattermost's own API. Effort depends far more on the code behind each bot than on the number of webhooks.
- Catalogue the code: Identify each slash command and bot, its owner, its source repository and every Slack API method it calls.
- Map the API surface: Compare each Slack method with its Mattermost equivalent. Where none exists, decide whether the feature is dropped or rebuilt around a webhook or a Mattermost plugin.
- Plan the identity model: Bots and their tokens need to be created in Mattermost, with permissions scoped to the channels they serve.
- Rewrite the interaction flow: Interactive messages, modals and button callbacks differ between platforms, so budget design and testing time for each user-facing flow.
For each bot, confirm with its owner whether it stores data in Slack or in an external system, because that determines whether the Slack export helps with its history.
An enterprise with many apps and Slack Connect channels has the largest rebuild, and the cost is spread across governance, dependencies and external parties. Many apps may be installed by different departments, some may be vendor-hosted SaaS tools with no Mattermost connector, and Slack Connect channels with partners or customers do not move in the Mattermost Slack migration path. Planning becomes a program, not a task list.
- Build a single register: Record every installed app, its scopes, its business owner and whether it can be replaced, rebuilt or retired. Include apps installed by individuals, since they are easy to miss.
- Handle Slack Connect separately: Shared channels with external organizations need a decision on whether those partners move, stay on Slack, or are reached through another channel. Mattermost's documented migration does not carry these channels across.
- Sequence by dependency: Some apps feed other systems, such as ticketing or incident tools. Rebuild the upstream sources first so that downstream consumers are not left without data.
- Involve security and compliance: Each rebuilt integration holds tokens and reads or writes business data, so review scopes and secret storage with the security team.
Ask your implementation partner to confirm, in writing, how each app and Slack Connect channel is handled, including which are retired and who signs off on each retirement.
What drives the cost and duration of rebuilding Slack bots
This table lists the factors that change how much work it takes to rebuild Slack apps, bots and webhooks on Mattermost, and how to keep each one under control. Read each row as a question to answer in your own inventory before you ask for a quote. Mattermost Team Edition is free, but SSO and AD/LDAP sync sit in paid Professional plans, and Mattermost publishes no list prices, so the licensing line depends on a sales conversation.
| Driver | Why it moves cost | How to reduce it |
|---|---|---|
| Number of integrations | Each Slack app, webhook and slash command needs its own inventory entry, rebuild, test and owner sign-off, so effort grows with the count rather than with the message history. | Export the list of installed apps and webhook URLs from Slack admin pages, then remove anything unused before any rebuild starts. |
| Custom code versus configuration | Apps built as custom Slack code need a new service on Mattermost, while simple incoming webhooks often need only a changed URL and payload check. | Sort integrations into webhook-only, slash command and custom app groups, and rebuild the simplest group first. |
| Payload complexity | Slack-style payloads that use mrkdwn, parse or link_names, <!everyone>, <!group>, <#CHANNEL_ID> links or single-asterisk bold need rewriting, and each rewrite needs a test. | Search every webhook body for these forms and convert them to the Mattermost equivalents before cutover. |
| Identity mapping and SSO | Bots and slash commands act as or mention real users, so mapping Slack user IDs to Mattermost accounts takes work. SSO (SAML, OIDC, OAuth) and AD/LDAP sync are included from the Professional plan, so identity design can change the licence needed. | Decide early whether accounts come from SSO or local login, build a user ID map from the migration export, and ask Mattermost which plan covers your identity model. |
| Slack Connect dependencies | Slack Connect channels and external integrations do not migrate, so any bot that posts into shared channels with partners needs a separate design, plus agreement from the external party. | List every bot that posts to a Slack Connect channel and decide per channel whether it moves, is retired, or waits for a guest or federation design. |
| Testing and sign-off | Each integration owner must confirm messages arrive in the right channel, with correct formatting, mentions and links. This is often the longest step because it depends on people outside the platform team. | Assign a named owner per integration, write a short test script for each, and schedule sign-off windows before the cutover date. |
| Admin time and vendor quotes | Platform admins, app owners and security reviewers all carry time, and Mattermost sells paid editions through a sales conversation with no public prices, so the quote depends on the scope you define. | Ask for a quote built from the integration inventory, the plan needed for SSO and sync, and the support hours for cutover, and confirm each assumption in writing. |
What usually goes wrong when Slack bots move to Mattermost
Most failures in a Slack-to-Mattermost move happen at the edges: integrations that post the wrong formatting, mentions that reach the wrong people, and bots that keep running against a Slack workspace nobody is watching. Each card below names one of these failure points and the check that prevents it before cutover.
Webhook formatting breaks silently
Mattermost accepts Slack-style incoming webhook payloads, but not every Slack parameter carries over. Requests without a Content-Type header take the payload= prefix, and Slack-style <url|text> links translate, yet mrkdwn, parse and link_names are not supported and *bold* with a single asterisk will not render as Slack users expect. Send a test payload from every webhook to a staging channel and compare the rendered output with what the Slack version showed.
Mentions notify the wrong people
Mattermost translates <!channel>, <!here> and <!all>, but <!everyone>, <!group> and <#CHANNEL_ID> channel links are not supported. A bot that posted <!everyone> in Slack may post plain text in Mattermost, so nobody is paged. Search every webhook and bot configuration for these forms and rewrite them to the Mattermost equivalents, then confirm that the on-call alias still receives a notification in a test channel.
Bots still running against Slack
After decommission, a Slack app can keep reading channels, posting alerts or holding a token that a former employee created. Inventory every Slack app with its installing user, scopes and channels, then revoke or disable each one in the same change window that closes the Slack workspace. Ask the Slack workspace owner to confirm the list is complete, since integrations do not appear in a channel export.
User groups lost in migration
The Mattermost Slack migration does not carry user groups across. Any workflow that routes approvals, on-call pages or access reviews to a Slack user group will stop reaching the intended team after import. Export the membership of each group from Slack, recreate the groups in Mattermost, and update every routing rule that referenced them before users start working in the new server.
History imported without its integrations
Messages from bots, alerts and approvals arrive in the import, but the apps that generated them do not. Users then see archived alerts with no way to act on them, and searches return context that points to integrations that no longer exist. Decide which historic channels need live integrations, and document which integrations were intentionally left behind so auditors and staff can see the gap was a decision.
Version drift after go-live
Mattermost releases a new server version in binary form on the 16th of each month, and v11.7 is an Extended Support Release supported until 2027-05-15. A bot tested on one release can break after an upgrade. Pin the server to a version you have tested, record which release that is, and schedule upgrades in a staging environment so integrations are retested before each production change.
What to confirm with Mattermost and your app owners before committing
Before you commit to Mattermost, confirm for every Slack integration whether a Mattermost-compatible replacement already exists or whether it must be rebuilt. Third-party Slack apps often rely on features that incoming webhooks do not carry over, such as mrkdwn, parse and link_names, or on <!everyone>, <!group> and <#CHANNEL_ID> formatting. Ask each app owner or vendor which Slack API methods the app calls, whether it uses slash commands, interactive message buttons or the Events API, and whether it needs a Mattermost bot account or an incoming webhook. Apps that depend on Slack's OAuth installation flow will not move by export alone, so treat them as rebuild items and record the owner, the target design and the test sign-off for each one.
Slack Connect channels need a separate decision. Mattermost's migration path does not carry Slack Connect channels, so confirm with business owners which external partners and customers still need a shared space after cutover. Options include inviting those people as guests on your Mattermost server, moving the conversation to a different channel the partner already uses, or keeping the Slack connection until the partner agrees to move. Record the data handling terms that apply to any external conversation before the cutover date, since the partner's own workspace policies will not change because yours did.
Decide where custom code runs and who owns it. Bots and webhook senders that your teams wrote usually live in a repository, a serverless function or a cron job on a server that already has Slack credentials. Confirm which of these are in scope, where they will be hosted inside your own network, how their secrets move to your secrets store, and who approves changes to the webhook URLs. Finally, verify current payload behavior against the Mattermost incoming webhooks documentation and run your own test payloads in a staging channel, covering attachments, emoji icons and mentions, because the documented compatibility list is the reference your app owners will be held to.
Questions teams ask before moving Slack apps to Mattermost
Do Slack apps and integrations migrate to Mattermost automatically?
No. Integrations do not move with a Slack export. Mattermost's documented Slack migration path, which converts an export with mmetl and loads it with mmctl, brings across users, channels, direct messages, threads and attachments, but not integrations, custom emoji images, user groups or Slack Connect channels. Every app, bot, slash command and webhook needs an inventory and a rebuild on the Mattermost side before cutover. Confirm the current import scope in the Mattermost Slack migration guide against your own export before you plan the work.
Which Slack export plan do we need to rebuild integrations?
The export plan does not decide whether integrations can be rebuilt, but it decides what history you can carry over. Every Slack plan can export messages and file links from public channels. Private channels and direct messages require a Business+ or Enterprise plan, and custom exports by member or conversation are limited to Enterprise. If your bots post into private channels or depend on DM history, confirm your export tier early, because an approved export request is a prerequisite for moving that content. Slack's export help article lists the options for each plan.
How much effort does rebuilding Slack integrations take, and what drives it?
Effort depends on the number of integrations, how much each one relies on Slack-specific behavior, and who owns the code. Simple incoming webhooks that send plain text often need only a URL change. Bots that use slash commands, interactive buttons, Slack formatting or the Slack API need redesign. Mattermost's incoming webhooks accept Slack-style payloads, but not every Slack field or mention form works, so each integration should be tested against its real payloads. Ask for a written inventory with a complexity rating per integration. No general duration is reliable without that list, because the number of unique integrations drives the work more than seat count.
Can our own team rebuild the Slack apps without outside help?
Often yes, if the team has developers who know the apps and access to their source code, and if the integrations are simple. Teams with a small number of webhooks usually handle the URL change and payload tests in house. Outside help adds value when bots use Slack features that Mattermost does not translate, when many business owners depend on the apps, or when the cutover must be tested under a fixed schedule. DeployOpen plans, implements, customizes, integrates and documents self-hosted platforms in your infrastructure and works under a fixed scope agreed in writing before work starts, so you can decide which integrations to keep in house and which to scope out.
What do app owners need to provide during the rebuild?
App owners need to confirm what each integration does, who depends on it, which channels it posts to, what credentials and scopes it uses, and what success looks like after cutover. They also need to provide access to the code, deployment environment and any secrets stored in Slack-side configuration. Owners should list every outbound call and inbound trigger, because webhook-only integrations are easy to miss in an export. Assign a named owner to each integration so testing and sign-off happen before the old Slack app is turned off.
How should we handle Slack Connect channels and user groups during the move?
Plan these separately, because neither moves with the standard export path. Slack Connect channels shared with customers or partners do not migrate, so you need an agreed replacement, such as guest accounts in Mattermost, and a security review of who gets access. User groups do not migrate either, so any mention, notification or access rule that used a group must be recreated as a Mattermost team, channel or group. Ask each owner which Slack Connect channels and user groups they rely on, and record the replacement decision before the cutover date.
Which Slack mention and formatting forms break in Mattermost webhooks?
Several do. Mattermost's incoming webhooks translate Slack-style links in the form of a URL with text and the channel, here and all mentions, but they do not support Slack's mrkdwn, parse and link_names parameters, the everyone and group mentions, channel links by ID, or single-asterisk bold. Engineers should search every integration for these forms and rewrite them, then test each message in a staging channel. Check the Mattermost incoming webhooks documentation for the exact supported set before you change code.
How DeployOpen scopes and runs a Slack to Mattermost integration migration
DeployOpen plans and implements a self-hosted Mattermost server inside the client's own infrastructure, then takes on the integration work that a Slack export does not carry across. In practice that means an inventory of every Slack app, slash command, incoming webhook and bot in use, a decision for each one (rebuild as a Mattermost webhook, rebuild as a slash command or bot account, or retire), and the code and configuration changes needed to make each one work. Engagements run under a fixed-scope written agreement that names the in-scope integrations, the deliverables, the test cases and the cutover criteria before work starts. DeployOpen also customizes and hardens the server, tests the rebuilt integrations, backs up the database and file storage, and documents the result. Ongoing upgrades, monitoring and continuous testing are available as a retainer, which matters because Mattermost publishes new server versions monthly and tracks support windows for each release.
Ask any provider, DeployOpen included, to show the integration inventory before agreeing on price. The inventory should record the Slack app name, who owns it, which channels it posts to, whether it uses attachments, blocks, mrkdwn or link_names, and whether it reads data back from Slack. Those answers determine the effort. A webhook that sends plain text with <!channel> mentions usually needs little change, while a bot that relies on Slack's Web API, interactive buttons or user groups is a rebuild. Confirm with your own security team which secrets, service accounts and network paths each integration needs, and where the webhook endpoints will live, since those controls are part of the hardening and testing scope. Also confirm the Slack plan your workspace is on, because it limits what history and private channel data can be exported in the first place. Any quote should separate the one-time build and cutover work from the recurring hosting, upgrade and support costs, and state which Mattermost edition the design assumes, because SSO and clustering are paid features.

