Skip to content
Choose a tag to compare


@Gargron Gargron released this
· 260 commits to main since this release
Choose a tag to compare


Note: This is a release candidate. It is intended to be stable, but not guaranteed.

Upgrade overview

This release contains upgrade notes that deviate from the norm:

ℹ️ Requires streaming API restart
ℹ️ Requires two-step database migration process for zero-downtime deployment
⚠️ Elasticsearch requirement raised to at least 7
⚠️ PostgreSQL version in docker-compose.yml has been changed from 9.6 to 14, requires manual upgrade

For more information, scroll down to the upgrade instructions section.



  • Add support for incoming edited posts (Gargron, Gargron, Gargron, Gargron, Gargron, Gargron, ClearlyClaire, Gargron, Gargron, ClearlyClaire, Gargron, Gargron, ClearlyClaire, ClearlyClaire, ClearlyClaire, ClearlyClaire, Gargron, Gargron, Gargron, ClearlyClaire, ClearlyClaire)
    • Previous versions remain available for perusal and comparison
    • People who reblogged a post are notified when it's edited
    • New REST APIs:
      • PUT /api/v1/statuses/:id
      • GET /api/v1/statuses/:id/history
      • GET /api/v1/statuses/:id/source
    • New streaming API event:
      • status.update
  • Add appeals for moderator decisions (Gargron, ClearlyClaire, ClearlyClaire, ClearlyClaire, Gargron, Gargron, ClearlyClaire, Gargron)
    • All default moderator decisions now notify the affected user by e-mail
    • They now link to an appeal page instead of suggesting replying to the e-mail
    • They can now be found in account settings and not just e-mail
    • Users can submit one appeal within 20 days of the decision
    • Moderators can approve or reject the appeal
  • Add notifications for posts deleted by moderators (Gargron, Gargron, Gargron, Gargron, Gargron)
    • New, redesigned report view in admin UI
    • Common report actions now only take one click to complete
    • Deleting posts or marking as sensitive from report now notifies user
    • Reports can be categorized by reason and specific rules violated
    • The reasons are automatically cited in the notifications, except for spam
    • Marking posts as sensitive now federates using post editing
  • Add explore page with trending posts and links (Gargron, Gargron, Gargron, Gargron, Gargron, Gargron, ClearlyClaire, Gargron, tribela, Gargron, Gargron, noiob, mayaeh, mayaeh, Gargron, mayaeh)
    • Hashtag trends algorithm is extended to work for posts and links
    • Links are only considered if they have an adequate preview card
    • Preview card generation has been improved to support structured data
    • Links can only trend if the publisher (domain) has been approved
    • Posts can only trend if the author has been approved
    • Individual approval and rejection for posts and links is also available
    • Moderators are notified about pending trends at most once every 2 hours
    • Posts and link trends are language-specific
    • Search page is redesigned into explore page in web UI
    • Discovery tab is coming soon in official iOS and Android apps
    • New REST APIs:
      • GET /api/v1/trends/links
      • GET /api/v1/trends/statuses
      • GET /api/v1/trends/tags (alias of GET /api/v1/trends)
      • GET /api/v1/admin/trends/links
      • GET /api/v1/admin/trends/statuses
      • GET /api/v1/admin/trends/tags
  • Add graphs and retention metrics to admin dashboard (Gargron, Gargron, ClearlyClaire, ClearlyClaire, ClearlyClaire, mashirozx, ClearlyClaire)
    • Dashboard shows more numbers with development over time
    • Other data such as most used interface languages and sign-up sources
    • User retention graph shows how many new users stick around
    • New REST APIs:
      • POST /api/v1/admin/measures
      • POST /api/v1/admin/dimensions
      • POST /api/v1/admin/retention
  • Add GET /api/v1/accounts/familiar_followers to REST API (Gargron)
  • Add POST /api/v1/accounts/:id/remove_from_followers to REST API (noellabo)
  • Add category and rule_ids params to POST /api/v1/reports IN REST API (Gargron, Gargron, Gargron)
    • category can be one of: spam, violation, other (default)
    • rule_ids must reference rules returned in GET /api/v1/instance
  • Add global lang param to REST API (Gargron, Gargron)
  • Add types param to GET /api/v1/notifications in REST API (Gargron)
  • Add notifications for moderators about new sign-ups (Gargron, ClearlyClaire)
    • When a new user confirms e-mail, moderators receive a notification
    • New notification type:
      • admin.sign_up
  • Add authentication history (Gargron, ClearlyClaire, baby-gnu)
  • Add ability to automatically delete old posts (ClearlyClaire, ClearlyClaire, tribela)
  • Add ability to pin private posts (ClearlyClaire, tribela, ClearlyClaire, MitarashiDango)
  • Add ability to filter search results by author using from: syntax (tribela)
  • Add ability to delete canonical email blocks in admin UI (ClearlyClaire)
  • Add ability to purge undeliverable domains in admin UI (ClearlyClaire, tribela, tribela, tribela)
  • Add ability to disable e-mail token authentication for specific users in admin UI (Gargron)
  • Add ability to suspend accounts in batches in admin UI (Gargron, ClearlyClaire, Gargron)
    • New, redesigned accounts list in admin UI
    • Batch suspensions are meant to help clean up spam and bot accounts
    • They do not generate notifications
  • Add ability to filter reports by origin of target account in admin UI (Gargron)
  • Add support for login through OpenID Connect (chandrn7)
  • Add lazy loading for emoji picker in web UI (mashirozx, ClearlyClaire)
  • Add single option votes tooltip in polls in web UI (Brawaru)
  • Add confirmation modal when closing media edit modal with unsaved changes in web UI (ClearlyClaire)
  • Add support for fetching Create and Announce activities by URI in ActivityPub (ClearlyClaire)
  • Add S3_FORCE_SINGLE_REQUEST environment variable (ClearlyClaire)
  • Add OMNIAUTH_ONLY environment variable (ClearlyClaire, ClearlyClaire)
  • Add ES_USER and ES_PASS environment variables for Elasticsearch authentication (tribela)
  • Add CAS_SECURITY_ASSUME_EMAIL_IS_VERIFIED environment variable (baby-gnu)
  • Add ability to pass specific domains to tootctl accounts cull (tribela)
  • Add --by-uri option to tootctl domains purge (ClearlyClaire)
  • Add --batch-size option to tootctl search deploy (aquarla)
  • Add --remove-orphans option to tootctl statuses remove (noellabo)



  • Remove profile directory link from main navigation panel in web UI (Gargron)
  • Remove language detection through cld3 (Gargron, ykzts, Gargron, Gargron)
    • cld3 is very inaccurate on short-form content even with unique alphabets
    • Post language can be overriden individually using language param
    • Otherwise, it defaults to the user's interface language
  • Remove support for OAUTH_REDIRECT_AT_SIGN_IN (ClearlyClaire)
    • Use OMNIAUTH_ONLY instead
  • Remove Keybase integration (Gargron)
  • Remove old columns and indexes (ClearlyClaire, Gargron, ClearlyClaire)
  • Remove shortcodes from newly-created media attachments (ClearlyClaire, ClearlyClaire)


  • GET /api/v1/trendsGET /api/v1/trends/tags
  • OAuth follow scope → read and/or write
  • text attribute on DELETE /api/v1/statuses/:idGET /api/v1/statuses/:id/source


  • Fix web manifest not permitting PWA usage from alternate domains (HolgerHuo)
  • Fix not being able to edit media attachments for scheduled posts (ClearlyClaire)
  • Fix subscribed relay activities being recorded as boosts (ClearlyClaire)
  • Fix streaming API server error messages when JSON parsing fails not specifying the source (ClearlyClaire)
  • Fix browsers autofilling new password field with old password (mashirozx)
  • Fix text being invisible before fonts load in web UI (tribela)
  • Fix public profile pages of unconfirmed users being accessible (ClearlyClaire, ClearlyClaire)
  • Fix nil error when trying to fetch key for signature verification (Gargron)
  • Fix null values being included in some indexes (Gargron)
  • Fix POST /api/v1/emails/confirmations not being available after sign-up (Gargron)
  • Fix rare race condition when reblogged post is deleted (ClearlyClaire, ClearlyClaire)
  • Fix being able to add more than 4 hashtags to hashtag column in web UI (Gargron)
  • Fix data integrity of featured tags (Gargron)
  • Fix performance of account timelines (Gargron)
  • Fix returning empty <p> tag for blank account note in REST API (Gargron)
  • Fix leak of existence of otherwise inaccessible posts in REST API (Gargron)
  • Fix not showing loading indicator when searching in web UI (Gargron)
  • Fix media modal footer's “external link” not being a link (ClearlyClaire)
  • Fix reply button on media modal not giving focus to compose form (ClearlyClaire)
  • Fix some media attachments being converted with too high framerates (ClearlyClaire)
  • Fix sign in token and warning emails failing to send when contact e-mail address is malformed (helloworldstack)
  • Fix opening the emoji picker scrolling the single-column view to the top (ClearlyClaire)
  • Fix edge case where settings/admin page sidebar would be incorrectly hidden (ClearlyClaire)
  • Fix performance of server-side filtering (ClearlyClaire)
  • Fix privacy policy link not being visible on small screens (Gargron)
  • Fix duplicate accounts when searching by IP range in admin UI (Gargron, tribela)
  • Fix error when performing a batch action on posts in admin UI (ClearlyClaire)
  • Fix deletes not being signed in authorized fetch mode (Gargron)
  • Fix Undo Announce sometimes inlining the originally Announced status (ClearlyClaire)
  • Fix localization of cold-start follow recommendations (Gargron, Gargron)
  • Fix replies collection incorrectly looping (ClearlyClaire)
  • Fix errors when multiple Delete are received for a given actor (ClearlyClaire)
  • Fixed prototype pollution bug and only allow trusted origin (r0hanSH)
  • Fix text being incorrectly pre-selected in composer textarea on /share (ClearlyClaire)
  • Fix SMTP_ENABLE_STARTTLS_AUTO/SMTP_TLS/SMTP_SSL environment variables don't work (kgtkr)
  • Fix media upload specific rate limits only being applied to v1 endpoint in REST API (tribela)
  • Fix media descriptions not being used for client-side filtering (ClearlyClaire)
  • Fix cold-start follow recommendation favouring older accounts due to wrong sorting (noellabo)
  • Fix not redirect to the right page after authenticating with WebAuthn (heguro)
  • Fix searching for additional hashtags in hashtag column (ClearlyClaire)
  • Fix color of hashtag column settings inputs (ClearlyClaire)
  • Fix performance of tootctl statuses remove (noellabo)
  • Fix tootctl accounts cull not excluding domains on timeouts and certificate issues (ClearlyClaire)
  • Fix 404 error when filtering admin action logs by non-existent target account (ClearlyClaire)
  • Fix error when accessing streaming API without any OAuth scopes (Brawaru)
  • Fix follow request count not updating when new follow requests arrive over streaming API in web UI (matildepark)
  • Fix error when unsuspending a local account (HolgerHuo)
  • Fix crash when a notification contains a not yet processed media attachment in web UI (ClearlyClaire)
  • Fix wrong color of download button in audio player in web UI (ClearlyClaire)
  • Fix notes for others accounts not being deleted when an account is deleted (ClearlyClaire)
  • Fix error when logging occurrence of unsupported video file (noellabo)
  • Fix wrong elements in trends widget being hidden on smaller screens in web UI (tribela)
  • Fix link to about page being displayed in limited federation mode (weex)
  • Fix styling of boost button in media modal not reflecting ability to boost (ClearlyClaire)
  • Fix OCR failure when erroneous lang data is in cache (ClearlyClaire)
  • Fix downloading media from blocked domains in tootctl media refresh (tribela)
  • Fix login form being displayed on landing page when already logged in (ClearlyClaire)
  • Fix polling for media processing status too frequently in web UI (tribela)
  • Fix hashtag autocomplete overriding user-typed case (weex)
  • Fix WebAuthn authentication setup to not prompt for PIN (truongnmt)

Upgrade notes

To get the code for v3.5.0rc1, use git fetch && git checkout v3.5.0rc1.

As always, make sure you have backups of the database before performing any upgrades. If you are using docker-compose, this is how a backup command might look: docker exec mastodon_db_1 pg_dump -Fc -U postgres postgres > name_of_the_backup.dump

ℹ️ Some S3-compatible storage providers (such as Tencent Cloud Object Storage) may require setting S3_FORCE_SINGLE_REQUEST=true to properly handle some requests.
ℹ️ OAUTH_REDIRECT_AT_SIGN_IN, which wasn't working as intended, has been replaced by an OMNIAUTH_ONLY environment variable that should address the same use case


Compatibility with Elasticsearch 6.x and earlier has been dropped, and Elasticsearch 7.x is now required for the optional full-text search feature. Other external dependencies have not changed, although the default Ruby version has changed if you are using rbenv (see below). To summarize, the dependency requirements for v3.5.0rc1 are:

  • Ruby: 2.5 to 3.1
  • PostgreSQL: 9.5 or newer
  • Elasticsearch (optional, for full-text search): 7.x
  • Redis: 4 or newer
  • Node: 12 or higher

Update steps

The following instructions are for updating from 3.4.6.

If you are upgrading directly from an earlier release, please carefully read the upgrade notes for the skipped releases as well, as they often require extra steps such as database migrations or dependency updates.


The PostgreSQL container version in our docker-compose.yml configuration has been changed from 9.6 to 14 due to EOL (End-of-Life) of 9.6. Detailed instructions on how to migrate your data is available here.

Non-Docker only:

  • If you are using rbenv, update the list of available versions and install Ruby 3.0.3 by doing RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.0.3
  • Install dependencies: bundle install and yarn install

Both Docker and non-Docker:

  1. Run the pre-deployment database migrations by specifying the SKIP_POST_DEPLOYMENT_MIGRATIONS=true environment variable:
    • Non-Docker: SKIP_POST_DEPLOYMENT_MIGRATIONS=true RAILS_ENV=production bundle exec rails db:migrate
    • Docker: docker-compose run --rm -e SKIP_POST_DEPLOYMENT_MIGRATIONS=true web rails db:migrate
  2. Precompile the assets:
    • Non-Docker: RAILS_ENV=production bundle exec rails assets:precompile
    • Docker: The assets are already precompiled during the build step
  3. Restart all Mastodon processes
  4. Clear cache:
    • Non-Docker: RAILS_ENV=production bin/tootctl cache clear
    • Docker: docker-compose run --rm web bin/tootctl cache clear
  5. Now that the new code is running, we can finish the database migrations. This will run the post-deployment ones:
    • Non-Docker: RAILS_ENV=production bundle exec rails db:migrate
    • Docker: docker-compose run --rm web rails db:migrate
  6. Restart all Mastodon processes