docs/main/administration-guide/onboard/migrate-from-slack.mdx
Mattermost provides a reliable migration path from Slack, enabling you to bring your organization’s collaboration history into a secure, self-hosted Mattermost environment. The migration process supports full workspaces, including users, channels and message history, direct messages, and threads so your teams can continue working without losing valuable context.
This process generally involves preparing your environment, exporting data from Slack, converting that data into a compatible format, and then importing it into Mattermost. Migrating from Slack is a multi-step process that can be complex, particularly for larger organizations or those with multiple Slack workspaces.
Additionally, please consider that Slack's data control policies or export capabilities may change at any time, or they may charge fees to customers for exporting data stored in Slack. Support for negotiating export of customer IP from Slack Enterprise can be requested by contacting a Mattermost Expert.
mmetl check slack.mmetl tool to parse and transform Slack exports.mmctl.These instructions outline a best effort migration path designed to preserve the majority of your messages, files, and workspace structure. Mattermost provides tools and guidance to help streamline the process, but manual adjustments during the data transformation and import steps are often required. Successful migration depends on careful planning and dedicating sufficient time, technical resources, and technical skills to the effort.
Depending on the size and complexity of your Slack environment, a full migration can take anywhere from several days to multiple weeks of dedicated effort. Larger organizations with multiple workspaces, extensive message history, and many files should expect the process to require significant iteration and testing before completion. It’s important to plan for this timeline in advance by allocating the necessary resources, scheduling time for trial imports in a development environment, and coordinating across teams. Building in extra time for adjustments during the transformation and import steps will help ensure a smoother transition and reduce disruption to your users.
Scoping the migration appropriately during the preparation step can significantly reduce processing time and allow for faster iteration. Before beginning, carefully consider what data is essential to bring over to Mattermost. Many organizations find that not every channel or file needs to be migrated, and focusing only on what is truly needed can save substantial processing time and manual effort. By setting clear boundaries early, you’ll minimize the amount of data that requires manual intervention and testing, which in turn shortens the migration timeline and helps avoid unnecessary complexity.
<Note>Consider talking to a Mattermost expert if your organization needs support migrating from Slack to Mattermost.
</Note>Before beginning the migration, it’s important to properly prepare your environment. Careful preparation helps reduce processing time, allows for faster iteration, and minimizes the chance of running into avoidable issues during the import.
This document assumes you already have a Mattermost Server deployed that is ready to accept your Slack data. If not, consider the recommendations in this section in conjunction with the appropriate deployment documentation to make informed decisions about your supporting database and file storage infrastructure.
Start by defining the scope of your migration:
The environment where you run the import can significantly affect performance:
mmetl tool is supported on Linux and macOS. Windows is not supported, and we do not recommend using Windows Subsystem for Linux (WSL) since the file system is not performant enough for the heavier processes involved in migration.Carefully preparing your environment and making these adjustments up front will help ensure the migration proceeds smoothly and reduces the need for repeated trial-and-error.
TeamSettings.MaxChannelsPerTeam: Set this to a number much higher than the number of channels you are migrating.TeamSettings.MaxUsersPerTeam: Set this to a number much higher than the number of users you are migrating.EmailSettings.EnableSignUpWithEmail and EmailSettings.EnableSignInWithEmail: Both must be set to trueFileSettings.MaxFileSize: Set this higher than the largest file in your Slack export.ElasticsearchSettings.EnableIndexing, ElasticsearchSettings > EnableSearching and ElasticsearchSettings.EnableAutocomplete: All must be set to false during the import to prevent performance issues. After the import, you can purge and reindex before enabling Elasticsearch.Slack offers two ways to export your data from their product.
You will receive a zip file containing the following contents:
channels.json)users.json)dms.json) (All channels export)groups.json) (All channels export)mpims.json) (All channels export)integration_logs.json)Avoid unzipping and rezipping the Slack export. Doing so can modify the directory structure of the archive which could cause issues with the import process.
Now that you have a Slack export file, let's convert it into Mattermost's bulk import format using the import preparation tool mmetl.
Download the latest release of mmetl for your OS and architecture. Run mmetl help to learn more about using the tool.
Before transforming, validate the integrity of your Slack export using the mmetl check command:
./mmetl check slack --file <SLACK EXPORT FILE>
This checks for structural issues in the export archive and reports any problems that may cause the transform or import to fail.
Run the command below to create a Mattermost bulk import file. Replace <TEAM-NAME> with the name of your team in Mattermost. Note that the name needs to be one word and lowercase (i.e. if you named your team My Team, <TEAM-NAME> would be my-team).
The team must already exist on your Mattermost server before importing, and Allow any user with an account on this server to join this team must be enabled for that team.
</Note>./mmetl transform slack --team <TEAM-NAME> --file <SLACK EXPORT FILE> --output mattermost_import.jsonl
The tool outputs a .jsonl file containing all of your users, channels, and posts. It also creates a data folder that contains all of your attachments. It doesn't matter what you name the .jsonl file. You can name it what you want with the --output flag as shown above. It just needs to be a .jsonl file.
The mmetl transform slack command supports several optional flags that can help with common migration scenarios:
--skip-attachments / -a: Skip copying attachments from the import file. Useful for faster iteration when testing the import process before including attachments.--allow-download / -l: Allow downloading attachments from URLs.--default-email-domain <DOMAIN>: When a user's email is missing from the export, generate one from their username and the provided domain (e.g., --default-email-domain example.com).--skip-empty-emails: Allow users with empty email addresses to be included in the output. Note that this results in invalid import data that will need to be manually corrected before importing.--discard-invalid-props / -p: Discard posts with invalid properties. By default, such posts are kept but imported without their properties.The mmetl transform process produces a transform-slack.log file that records INFO level output by default.
If you run the import commands with the --debug flag, the log will include additional DEBUG level entries. These entries provide more granular detail on each phase of the process, which can help identify where the transformation may be slowing down or failing.
When parsing a Slack export file with the mmetl tool, the process runs through four phases. You can track progress by monitoring the log output during each phase. Understanding these phases helps set expectations for how long the parsing step may take.
1. Reading the import file
In this phase, mmetl reads through the Slack export file. Example log line:
{"file":"parse.go:359","level":"info","msg":"Processing file 1 of 10335: aluminum-white-lightbulb/","time":"2024-03-11T20:41:09-04:00"}
This step usually takes 5–10 minutes depending on the size of the export archive.
2. Converting user mentions
During this phase, mmetl converts Slack user mentions into Mattermost-compatible format. Example log line:
{"file":"parse.go:224","level":"debug","msg":"Slack Import: converting user mentions for channel touchscreen-headphones-sleek. 1 of 400","time":"2024-03-11T20:41:10-04:00"}
This step can be time-consuming on large imports and may take several hours.
3. Converting channel mentions
In this phase, channel references are updated. Example log line:
{"file":"parse.go:259","level":"debug","msg":"Slack Import: converting channel mentions for channel robust-smart-home-device-matrix. 95 of 400","time":"2024-03-11T20:41:48-04:00"}
This step typically completes in about half the time required for user mentions.
4. Converting post markup
Finally, Slack message formatting is converted into Mattermost-compatible Markdown. Example log line:
{"file":"parse.go:330","level":"debug","msg":"Slack Import: converting markdown for channel vertex-robust-vacuum. 120 of 400","time":"2024-03-11T20:41:58-04:00"}
This is the fastest step and usually completes quickly.
You can upload the export through Mattermost's API from the server or from another computer using mmctl commands. The server will save the import in its file store before running the import (e.g. AWS S3), so there will be time spent uploading/downloading the file in this case.
The migration is idempotent, meaning that you can run multiple imports that contain the same posts, and there won't be duplicated created posts in Mattermost. Each post is imported with the correct user/author and created_at value from your Slack instance.
Ensure you have the Mattermost command line tool mmctl installed. This allows you to perform different tasks that communicate to Mattermost's API. You'll also want to configure authentication for the tool.
To prepare our files to be uploaded to the server, we need to put both the .jsonl file and data folder together into a zip file.
zip -r mattermost-bulk-import.zip data mattermost_import.jsonl
Validate the import file locally before uploading. This checks the file structure and content without needing to upload it to the server:
mmctl import validate ./mattermost-bulk-import.zip
Then we can upload the zip file to our Mattermost server. These files can be very large, so getting them onto the server can be challenging. You have two primary options for this step:
You can use the mmctl tool:
mmctl import upload ./mattermost-bulk-import.zip
Alternatively, you can move the file directly to the data directory under data/import and give it a unique name.
Run this command to list the available imports:
mmctl import list available
Run this command to process the import. Replace <IMPORT FILE NAME> with the name you got from the mmctl import list available command:
mmctl import process <IMPORT FILE NAME>
Finally, run this command to view the status of the import process job. If the job status shows as pending, then wait before running the command again. The --json flag is required to view the possible error message. Replace <JOB ID> with the id you got from the mmctl import job list command:
mmctl import job show <JOB ID> --json
You can use the mmctl import job show command to view any relevant errors that may have occurred.
After importing, all messages may appear as unread for users. To resolve this issue, run the following SQL queries directly against the Mattermost database:
begin;
UPDATE channelmembers
SET
msgcount = channels.totalmsgcount,
lastupdateat = channels.lastpostat,
lastviewedat = channels.lastpostat,
msgcountroot = channels.totalmsgcountroot
FROM channels
WHERE channelmembers.channelid = channels.id;
INSERT INTO preferences (UserId, Category, Name, Value)
SELECT
cm.userid,
'channel_approximate_view_time',
cm.channelid,
cm.lastupdateat
FROM
channelmembers cm
ON CONFLICT (userid, category, name)
DO UPDATE SET
Value = EXCLUDED.Value;
update preferences
set value = false
where category = 'direct_channel_show';
update preferences
set value = false
where category = 'group_channel_show';
commit;
During the import process, the emails and usernames from Slack are used to create new Mattermost accounts. If emails are not present in the Slack export archive, then placeholder values will be generated and the system admin will need to update these manually. We recommend administrators search the final import jsonl file for user lines with @example.com in the email property to address and resolve the missing information prior to import.
The email verification process during Slack import depends on who performs the import:
System administrator imports:
Non-administrator imports:
What additional considerations are there for Slack Enterprise Grid? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Slack Enterprise Grid combines multiple workspaces under a single management plane and the associated export reflects that complexity. An Enterprise Grid export is a single archive containing all workspaces and shared channels.
Mattermost does not support shared channels between teams, so Slack Shared Channels must be mapped to a single team in Mattermost. We can create this mapping by determining the originating teams in Slack and creating a team.json mapping file for use with mmetl. Because of the manual effort required to identify and map team IDs, Enterprise Grid migrations are typically more time-consuming than single-workspace migrations. Plan additional time and resources to complete this step successfully.
At the root level, you’ll see shared channels that span across Slack workspaces, and under /teams/ you’ll find per-workspace data such as channels and users files. A typical structure looks like:
Enterprise Grid Export/
├── channel1/
│ ├── 2023-01-01.json
│ └── 2023-01-02.json
├── channel2/
│ ├── 2023-05-01.json
│ └── 2023-05-02.json
├── teams/
│ ├── team1/
│ │ ├── channel3/
│ │ │ ├── 2023-05-01.json
│ │ │ └── 2023-05-02.json
│ │ ├── channels.json
│ │ ├── mpims.json
│ │ ├── dms.json
│ │ ├── users.json
│ │ └── groups.json
│ └── team2/
│ ├── channel4/
│ │ ├── 2023-05-01.json
│ │ └── 2023-05-02.json
│ ├── channels.json
│ ├── mpims.json
│ ├── dms.json
│ ├── users.json
│ └── groups.json
├── channels.json
├── org_users.json
├── mpims.json
├── dms.json
└── groups.json
team attribute on the first post in each shared channel. These team values map the channel back to its originating workspace in Slack. This is where each shared channel will live in Mattermost once imported.json{ "client_msg_id": "", "type": "", "text": "", "user": "U1", "ts": "1695219722.430309", "blocks": [ ], "team": "team1", "user_team": "team1", "source_team": "team1", "user_profile": { } },
teams.json file that maps Slack team IDs to each team attribute you found above. For example:json{ "T0001" : "team1", "T0002" : "team2" }
mmetl grid-transform command to split the Enterprise Grid export into per-team files:bash./mmetl grid-transform -f slackexport.zip -t teams.json
This process outputs a new archive for each team defined in teams.json. Once split, you can continue the standard Mattermost import process on each file.
The Slack import process focuses on preserving core collaboration data such as messages, files, channels, and users. However, certain Slack features are not supported by the Mattermost product and thus will not be migrated using the import tools in this document:
Because of these limitations, some manual reconfiguration is typically required after the import, especially for workflows and integrations. Support from a Mattermost expert is available for your Slack migration.