diff --git a/.github/workflows/osx.yml b/.github/workflows/osx.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b3af72d21ebc3d78b86ceb141f54094a702561f7
--- /dev/null
+++ b/.github/workflows/osx.yml
@@ -0,0 +1,102 @@
+name: osx
+
+on:
+  schedule:
+    - cron: '0 1 * * *'
+  workflow_dispatch:
+
+jobs:
+  osx:
+    # Run for tarantool/tarantool repository only.
+    if: github.repository == 'tarantool/tarantool'
+
+    runs-on:
+      - 'macos-${{ matrix.osx-version }}-self-hosted'
+      - '${{ matrix.machine-arch }}'
+
+    strategy:
+      fail-fast: false
+      matrix:
+        osx-version: [ 13 ]
+        machine-arch: [ x86_64, aarch64 ]
+        tarantool-branch:
+          - 'master'
+          - 'release/3.0'
+          - 'release/2.11'
+          - 'release/2.10'
+        build-type: [ debug, release, release-lto, static-cmake ]
+        include:
+          - osx-version: 12
+            machine-arch: x86_64
+            tarantool-branch: 'master'
+            build-type: release
+          - osx-version: 12
+            machine-arch: x86_64
+            tarantool-branch: 'release/3.0'
+            build-type: release
+          - osx-version: 12
+            machine-arch: x86_64
+            tarantool-branch: 'release/2.11'
+            build-type: release
+          - osx-version: 12
+            machine-arch: x86_64
+            tarantool-branch: 'release/2.10'
+            build-type: release
+
+    env:
+      BUILD_TYPE: ${{ matrix.build-type }}
+
+    steps:
+      - name: Prepare checkout
+        uses: tarantool/actions/prepare-checkout@master
+
+      - name: Sources checkout
+        uses: actions/checkout@v3
+        with:
+          ref: ${{ matrix.tarantool-branch }}
+          fetch-depth: 0
+          submodules: recursive
+
+      - uses: ./.github/actions/environment
+
+      - name: Install deps
+        uses: ./.github/actions/install-deps-osx
+
+      - name: Enable LTO for build
+        if: endsWith(matrix.build-type, '-lto')
+        run: |
+          echo "BUILD_TYPE=${BUILD_TYPE/-lto/}" >> $GITHUB_ENV
+          echo "CMAKE_EXTRA_PARAMS=-DENABLE_LTO=ON" >> $GITHUB_ENV
+
+      - name: Run testing
+        run: make -f .test.mk test-osx-${{ env.BUILD_TYPE }}
+
+      - name: Send VK Teams message on failure
+        if: failure()
+        uses: ./.github/actions/report-job-status
+        with:
+          bot-token: ${{ secrets.VKTEAMS_BOT_TOKEN }}
+
+      - name: Upload artifacts
+        uses: actions/upload-artifact@v3
+        if: failure()
+        with:
+          name: ${{ format(
+            'osx-{0}-{1}-{2}-{3}',
+            matrix.osx-version,
+            matrix.machine-arch,
+            matrix.tarantool-branch,
+            matrix.build-type) }}
+          retention-days: 21
+          path: ${{ env.VARDIR }}/artifacts
+
+      - name: Upload artifacts to S3
+        uses: ./.github/actions/s3-upload-artifact
+        if: ( success() || failure() ) && ( github.ref == 'refs/heads/master' ||
+          startsWith(github.ref, 'refs/heads/release/') ||
+          startsWith(github.ref, 'refs/tags/') )
+        with:
+          job-name: ${{ github.job }} (${{ join(matrix.*, ', ') }})
+          access-key-id: ${{ secrets.MULTIVAC_S3_ACCESS_KEY_ID }}
+          secret-access-key: ${{ secrets.MULTIVAC_S3_SECRET_ACCESS_KEY }}
+          source: ${{ env.VARDIR }}/artifacts
diff --git a/.github/workflows/osx_debug.yml b/.github/workflows/osx_debug.yml
deleted file mode 100644
index bdc1dec28cf22ce5b7548c9f1dede249067d44b8..0000000000000000000000000000000000000000
--- a/.github/workflows/osx_debug.yml
+++ /dev/null
@@ -1,98 +0,0 @@
-name: osx_debug
-
-on:
-  push:
-    branches:
-      - 'master'
-      - 'release/**'
-    tags:
-      - '**'
-  pull_request:
-  workflow_dispatch:
-  workflow_call:
-    inputs:
-      submodule:
-        description: Name of submodule to bump.
-        required: true
-        type: string
-      revision:
-        description: Git revision from submodule repository
-        required: true
-        type: string
-
-concurrency:
-  # Update of a developer branch cancels the previously scheduled workflow
-  # run for this branch. However, the 'master' branch, release branch, and
-  # tag workflow runs are never canceled.
-  #
-  # We use a trick here: define the concurrency group as 'workflow run ID' +
-  # 'workflow run attempt' because it is a unique combination for any run.
-  # So it effectively discards grouping.
-  #
-  # Important: we cannot use `github.sha` as a unique identifier because
-  # pushing a tag may cancel a run that works on a branch push event.
-  group: ${{ (
-    github.ref == 'refs/heads/master' ||
-    startsWith(github.ref, 'refs/heads/release/') ||
-    startsWith(github.ref, 'refs/tags/')) &&
-    format('{0}-{1}', github.run_id, github.run_attempt) ||
-    format('{0}-{1}', github.workflow, github.ref) }}
-  cancel-in-progress: true
-
-jobs:
-  osx_debug:
-    # Run on push to the 'master' and release branches of tarantool/tarantool
-    # or on pull request if the 'notest' label is not set.
-    if: github.repository == 'tarantool/tarantool' &&
-        ( github.event_name != 'pull_request' ||
-          ( github.event_name == 'pull_request' &&
-            !contains(github.event.pull_request.labels.*.name, 'notest') ) )
-
-    runs-on: [ 'macos-${{ matrix.version }}-self-hosted', '${{ matrix.arch }}' ]
-
-    strategy:
-      fail-fast: false
-      matrix:
-        version: [ 13 ]
-        arch: [ x86_64, aarch64 ]
-
-    steps:
-      - name: Prepare checkout
-        uses: tarantool/actions/prepare-checkout@master
-      - uses: actions/checkout@v3
-        with:
-          fetch-depth: 0
-          submodules: recursive
-      - uses: ./.github/actions/environment
-      - name: Install deps
-        uses: ./.github/actions/install-deps-osx
-      - name: Optional submodule bump
-        if: ${{ inputs.submodule }}
-        uses: ./.github/actions/bump-submodule
-        with:
-          submodule: ${{ inputs.submodule }}
-          revision: ${{ inputs.revision }}
-      - name: test
-        run: make -f .test.mk test-osx-debug
-      - name: Send VK Teams message on failure
-        if: failure()
-        uses: ./.github/actions/report-job-status
-        with:
-          bot-token: ${{ secrets.VKTEAMS_BOT_TOKEN }}
-      - name: artifacts
-        uses: actions/upload-artifact@v3
-        if: failure()
-        with:
-          name: osx-${{ matrix.version }}-debug-${{ matrix.arch }}
-          retention-days: 21
-          path: ${{ env.VARDIR }}/artifacts
-      - name: Upload artifacts to S3
-        uses: ./.github/actions/s3-upload-artifact
-        if: ( success() || failure() ) && ( github.ref == 'refs/heads/master' ||
-          startsWith(github.ref, 'refs/heads/release/') ||
-          startsWith(github.ref, 'refs/tags/') )
-        with:
-          job-name: ${{ github.job }} (${{ join(matrix.*, ', ') }})
-          access-key-id: ${{ secrets.MULTIVAC_S3_ACCESS_KEY_ID }}
-          secret-access-key: ${{ secrets.MULTIVAC_S3_SECRET_ACCESS_KEY }}
-          source: ${{ env.VARDIR }}/artifacts
diff --git a/.github/workflows/osx_release.yml b/.github/workflows/osx_release.yml
deleted file mode 100644
index 4cb467298b5e505b52a652bba29f79621088fd97..0000000000000000000000000000000000000000
--- a/.github/workflows/osx_release.yml
+++ /dev/null
@@ -1,101 +0,0 @@
-name: osx_release
-
-on:
-  push:
-    branches:
-      - 'master'
-      - 'release/**'
-    tags:
-      - '**'
-  pull_request:
-  workflow_dispatch:
-  workflow_call:
-    inputs:
-      submodule:
-        description: Name of submodule to bump.
-        required: true
-        type: string
-      revision:
-        description: Git revision from submodule repository
-        required: true
-        type: string
-
-concurrency:
-  # Update of a developer branch cancels the previously scheduled workflow
-  # run for this branch. However, the 'master' branch, release branch, and
-  # tag workflow runs are never canceled.
-  #
-  # We use a trick here: define the concurrency group as 'workflow run ID' +
-  # 'workflow run attempt' because it is a unique combination for any run.
-  # So it effectively discards grouping.
-  #
-  # Important: we cannot use `github.sha` as a unique identifier because
-  # pushing a tag may cancel a run that works on a branch push event.
-  group: ${{ (
-    github.ref == 'refs/heads/master' ||
-    startsWith(github.ref, 'refs/heads/release/') ||
-    startsWith(github.ref, 'refs/tags/')) &&
-    format('{0}-{1}', github.run_id, github.run_attempt) ||
-    format('{0}-{1}', github.workflow, github.ref) }}
-  cancel-in-progress: true
-
-jobs:
-  osx_release:
-    # Run on push to the 'master' and release branches of tarantool/tarantool
-    # or on pull request if the 'notest' label is not set.
-    if: github.repository == 'tarantool/tarantool' &&
-        ( github.event_name != 'pull_request' ||
-          ( github.event_name == 'pull_request' &&
-            !contains(github.event.pull_request.labels.*.name, 'notest') ) )
-
-    runs-on: [ 'macos-${{ matrix.version }}-self-hosted', '${{ matrix.arch }}' ]
-
-    strategy:
-      fail-fast: false
-      matrix:
-        version: [ 13 ]
-        arch: [ x86_64, aarch64 ]
-        include:
-          - version: 12
-            arch: x86_64
-
-    steps:
-      - name: Prepare checkout
-        uses: tarantool/actions/prepare-checkout@master
-      - uses: actions/checkout@v3
-        with:
-          fetch-depth: 0
-          submodules: recursive
-      - uses: ./.github/actions/environment
-      - name: Install deps
-        uses: ./.github/actions/install-deps-osx
-      - name: Optional submodule bump
-        if: ${{ inputs.submodule }}
-        uses: ./.github/actions/bump-submodule
-        with:
-          submodule: ${{ inputs.submodule }}
-          revision: ${{ inputs.revision }}
-      - name: test
-        run: make -f .test.mk test-osx-release
-      - name: Send VK Teams message on failure
-        if: failure()
-        uses: ./.github/actions/report-job-status
-        with:
-          bot-token: ${{ secrets.VKTEAMS_BOT_TOKEN }}
-      - name: artifacts
-        uses: actions/upload-artifact@v3
-        if: failure()
-        with:
-          name: osx-${{ matrix.version }}-release-${{ matrix.arch }}
-          retention-days: 21
-          path: ${{ env.VARDIR }}/artifacts
-      - name: Upload artifacts to S3
-        uses: ./.github/actions/s3-upload-artifact
-        if: ( success() || failure() ) && ( github.ref == 'refs/heads/master' ||
-          startsWith(github.ref, 'refs/heads/release/') ||
-          startsWith(github.ref, 'refs/tags/') )
-        with:
-          job-name: ${{ github.job }} (${{ join(matrix.*, ', ') }})
-          access-key-id: ${{ secrets.MULTIVAC_S3_ACCESS_KEY_ID }}
-          secret-access-key: ${{ secrets.MULTIVAC_S3_SECRET_ACCESS_KEY }}
-          source: ${{ env.VARDIR }}/artifacts
diff --git a/.github/workflows/osx_release_lto.yml b/.github/workflows/osx_release_lto.yml
deleted file mode 100644
index 5f5bffb159a07a2b84a53e58970d0a13cd90af6c..0000000000000000000000000000000000000000
--- a/.github/workflows/osx_release_lto.yml
+++ /dev/null
@@ -1,100 +0,0 @@
-name: osx_release_lto
-
-on:
-  push:
-    branches:
-      - 'master'
-      - 'release/**'
-    tags:
-      - '**'
-  pull_request:
-    types: [opened, reopened, synchronize, labeled]
-  workflow_dispatch:
-  workflow_call:
-    inputs:
-      submodule:
-        description: Name of submodule to bump.
-        required: true
-        type: string
-      revision:
-        description: Git revision from submodule repository
-        required: true
-        type: string
-
-concurrency:
-  # Update of a developer branch cancels the previously scheduled workflow
-  # run for this branch. However, the 'master' branch, release branch, and
-  # tag workflow runs are never canceled.
-  #
-  # We use a trick here: define the concurrency group as 'workflow run ID' +
-  # 'workflow run attempt' because it is a unique combination for any run.
-  # So it effectively discards grouping.
-  #
-  # Important: we cannot use `github.sha` as a unique identifier because
-  # pushing a tag may cancel a run that works on a branch push event.
-  group: ${{ (
-    github.ref == 'refs/heads/master' ||
-    startsWith(github.ref, 'refs/heads/release/') ||
-    startsWith(github.ref, 'refs/tags/')) &&
-    format('{0}-{1}', github.run_id, github.run_attempt) ||
-    format('{0}-{1}', github.workflow, github.ref) }}
-  cancel-in-progress: true
-
-jobs:
-  osx_release_lto:
-    # Run on push to the 'master' and release branches of tarantool/tarantool
-    # or on pull request if the 'full-ci' label is set.
-    if: github.repository == 'tarantool/tarantool' &&
-        ( github.event_name != 'pull_request' ||
-          contains(github.event.pull_request.labels.*.name, 'full-ci') )
-
-    runs-on: [ 'macos-${{ matrix.version }}-self-hosted', '${{ matrix.arch }}' ]
-
-    strategy:
-      fail-fast: false
-      matrix:
-        version: [ 13 ]
-        arch: [ x86_64, aarch64 ]
-
-    steps:
-      - name: Prepare checkout
-        uses: tarantool/actions/prepare-checkout@master
-      - uses: actions/checkout@v3
-        with:
-          fetch-depth: 0
-          submodules: recursive
-      - uses: ./.github/actions/environment
-      - name: Install deps
-        uses: ./.github/actions/install-deps-osx
-      - name: Optional submodule bump
-        if: ${{ inputs.submodule }}
-        uses: ./.github/actions/bump-submodule
-        with:
-          submodule: ${{ inputs.submodule }}
-          revision: ${{ inputs.revision }}
-      - name: test
-        env:
-          CMAKE_EXTRA_PARAMS: -DENABLE_LTO=ON
-        run: make -f .test.mk test-osx-release
-      - name: Send VK Teams message on failure
-        if: failure()
-        uses: ./.github/actions/report-job-status
-        with:
-          bot-token: ${{ secrets.VKTEAMS_BOT_TOKEN }}
-      - name: artifacts
-        uses: actions/upload-artifact@v3
-        if: failure()
-        with:
-          name: osx-${{ matrix.version }}-release-lto-${{ matrix.arch }}
-          retention-days: 21
-          path: ${{ env.VARDIR }}/artifacts
-      - name: Upload artifacts to S3
-        uses: ./.github/actions/s3-upload-artifact
-        if: ( success() || failure() ) && ( github.ref == 'refs/heads/master' ||
-          startsWith(github.ref, 'refs/heads/release/') ||
-          startsWith(github.ref, 'refs/tags/') )
-        with:
-          job-name: ${{ github.job }} (${{ join(matrix.*, ', ') }})
-          access-key-id: ${{ secrets.MULTIVAC_S3_ACCESS_KEY_ID }}
-          secret-access-key: ${{ secrets.MULTIVAC_S3_SECRET_ACCESS_KEY }}
-          source: ${{ env.VARDIR }}/artifacts
diff --git a/.github/workflows/osx_static_cmake.yml b/.github/workflows/osx_static_cmake.yml
deleted file mode 100644
index 621dfa0ac87f1b443c56c831d2219a0e53c937d3..0000000000000000000000000000000000000000
--- a/.github/workflows/osx_static_cmake.yml
+++ /dev/null
@@ -1,99 +0,0 @@
-name: osx_static_cmake
-
-on:
-  push:
-    branches:
-      - 'master'
-      - 'release/**'
-    tags:
-      - '**'
-  pull_request:
-    types: [opened, reopened, synchronize, labeled]
-  workflow_dispatch:
-  workflow_call:
-    inputs:
-      submodule:
-        description: Name of submodule to bump.
-        required: true
-        type: string
-      revision:
-        description: Git revision from submodule repository
-        required: true
-        type: string
-
-concurrency:
-  # Update of a developer branch cancels the previously scheduled workflow
-  # run for this branch. However, the 'master' branch, release branch, and
-  # tag workflow runs are never canceled.
-  #
-  # We use a trick here: define the concurrency group as 'workflow run ID' +
-  # 'workflow run attempt' because it is a unique combination for any run.
-  # So it effectively discards grouping.
-  #
-  # Important: we cannot use `github.sha` as a unique identifier because
-  # pushing a tag may cancel a run that works on a branch push event.
-  group: ${{ (
-    github.ref == 'refs/heads/master' ||
-    startsWith(github.ref, 'refs/heads/release/') ||
-    startsWith(github.ref, 'refs/tags/')) &&
-    format('{0}-{1}', github.run_id, github.run_attempt) ||
-    format('{0}-{1}', github.workflow, github.ref) }}
-  cancel-in-progress: true
-
-jobs:
-  osx_static_cmake:
-    # Run on push to the 'master' and release branches of tarantool/tarantool
-    # or on pull request if the 'full-ci' or 'static-build-ci' label is set.
-    if: github.repository == 'tarantool/tarantool' &&
-        ( github.event_name != 'pull_request' ||
-          contains(github.event.pull_request.labels.*.name, 'full-ci') ||
-          contains(github.event.pull_request.labels.*.name, 'static-build-ci') )
-
-    runs-on: [ 'macos-${{ matrix.version }}-self-hosted', '${{ matrix.arch }}' ]
-
-    strategy:
-      fail-fast: false
-      matrix:
-        version: [ 13 ]
-        arch: [ x86_64, aarch64 ]
-
-    steps:
-      - name: Prepare checkout
-        uses: tarantool/actions/prepare-checkout@master
-      - uses: actions/checkout@v3
-        with:
-          fetch-depth: 0
-          submodules: recursive
-      - uses: ./.github/actions/environment
-      - name: Install deps
-        uses: ./.github/actions/install-deps-osx
-      - name: Optional submodule bump
-        if: ${{ inputs.submodule }}
-        uses: ./.github/actions/bump-submodule
-        with:
-          submodule: ${{ inputs.submodule }}
-          revision: ${{ inputs.revision }}
-      - name: test
-        run: make -f .test.mk test-osx-static-cmake
-      - name: Send VK Teams message on failure
-        if: failure()
-        uses: ./.github/actions/report-job-status
-        with:
-          bot-token: ${{ secrets.VKTEAMS_BOT_TOKEN }}
-      - name: artifacts
-        uses: actions/upload-artifact@v3
-        if: failure()
-        with:
-          name: osx-${{ matrix.version }}-static-cmake-${{ matrix.arch }}
-          retention-days: 21
-          path: ${{ env.VARDIR }}/artifacts
-      - name: Upload artifacts to S3
-        uses: ./.github/actions/s3-upload-artifact
-        if: ( success() || failure() ) && ( github.ref == 'refs/heads/master' ||
-          startsWith(github.ref, 'refs/heads/release/') ||
-          startsWith(github.ref, 'refs/tags/') )
-        with:
-          job-name: ${{ github.job }} (${{ join(matrix.*, ', ') }})
-          access-key-id: ${{ secrets.MULTIVAC_S3_ACCESS_KEY_ID }}
-          secret-access-key: ${{ secrets.MULTIVAC_S3_SECRET_ACCESS_KEY }}
-          source: ${{ env.VARDIR }}/artifacts