diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml
index 8c6d58a82a7c046d326fe2fcc72b32623431deb0..107ac9c1a66583199071387fbb53d3c95de1d13f 100644
--- a/.github/workflows/build-binaries.yml
+++ b/.github/workflows/build-binaries.yml
@@ -1,5 +1,8 @@
-# This script will build session production binaries anytime a branch is updated
-name: Session Build Binaries
+# There is a fair bit of duplication here, but it is the best to save our github free minutes for now.
+# We could save and restore cache to different jobs but that takes roughly 3 minutes to save,
+# so better run them in parrallel instead.
+
+name: Session Desktop
 
 on:
   push:
@@ -19,66 +22,141 @@ concurrency:
   group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
   cancel-in-progress: true
 
+env:
+  # we want to publish on "push to master" only. When we don't want to publish, we want to upload artefacts
+  SHOULD_PUBLISH: ${{ github.event_name == 'push' && github.ref == 'master' }}
+
 jobs:
-  build:
-    runs-on: ${{ matrix.os }}
+  build_linux:
+    runs-on: ubuntu-20.04
     strategy:
-      fail-fast: false
       matrix:
-        # We want a mac arm64 build, and according to this https://github.com/actions/runner-images#available-images macos-14 is always arm64
-        # macos-14 is disabled for now as we hit our free tier limit for macos builds
-        os: [windows-2022, ubuntu-20.04, macos-12]
+        # this needs to be a valid target of https://www.electron.build/linux#target
+        pkg_to_build: ['deb', 'rpm', 'freebsd', 'AppImage']
+
     env:
-      SIGNAL_ENV: production
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
       - run: git config --global core.autocrlf false
 
       - name: Checkout git repo
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Setup & Build
         uses: ./actions/setup_and_build
+        with:
+          cache_suffix: ${{ matrix.pkg_to_build }}
+
+      - name: Lint Files
+        # no need to lint files on all platforms
+        run: yarn lint-full
 
       - name: Enforce yarn.lock has no duplicates
+        # no need to dedup yarn.lock on all platforms
         uses: ./actions/deduplicate_fail
 
-      - name: Build windows production binaries
-        if: runner.os == 'Windows'
-        run: node_modules\.bin\electron-builder --config.extraMetadata.environment=%SIGNAL_ENV% --publish=never --config.directories.output=release
+        # we want to test on all platforms since some are testing the rendered menus (and are dependent on the platform)
+      - name: Unit Test
+        run: yarn test
 
-      - name: Build mac production binaries
-        if: runner.os == 'macOS'
+      - name: Build but do not publish ${{ matrix.pkg_to_build }}
+        # we want this to run always, except on "push" to "master"
+        if: ${{ env.SHOULD_PUBLISH == 'false' }}
         run: |
-          source ./build/setup-mac-certificate.sh
-          $(yarn bin)/electron-builder --config.extraMetadata.environment=$SIGNAL_ENV --config.mac.bundleVersion=${{ github.ref }} --publish=never --config.directories.output=release
-        env:
-          MAC_CERTIFICATE: ${{ secrets.MAC_CERTIFICATE }}
-          MAC_CERTIFICATE_PASSWORD: ${{ secrets.MAC_CERTIFICATE_PASSWORD }}
-          SIGNING_APPLE_ID: ${{ secrets.SIGNING_APPLE_ID }}
-          SIGNING_APP_PASSWORD: ${{ secrets.SIGNING_APP_PASSWORD }}
-          SIGNING_TEAM_ID: ${{ secrets.SIGNING_TEAM_ID }}
-
-      - name: Build linux production binaries
-        if: runner.os == 'Linux'
+          sed -i 's/"target": \["deb"\]/"target": "${{ matrix.pkg_to_build }}"/g' package.json && yarn build-release
+
+      - name: Upload artefacts ${{ matrix.pkg_to_build }}
+        # we want this to run always, except on "push" to "master"
+        if: ${{ env.SHOULD_PUBLISH == 'false' }}
+        uses: ./actions/upload_prod_artefacts
+        with:
+          upload_prefix: ${{ runner.os }}-${{ runner.arch }}-${{ matrix.pkg_to_build }}
+
+      - name: Build & publish ${{ matrix.pkg_to_build }}
+        # we want this to run only when on "push" to "master"
+        if: ${{ env.SHOULD_PUBLISH == 'true' }}
         run: |
-          sudo apt-get install -y rpm
-          yarn build-release
+          sed -i 's/\"target\": \\[\"deb\"\\]/\"target\": \"${{ matrix.pkg_to_build }}\"/g' package.json; yarn build-release-publish
+
+  build_windows:
+    runs-on: windows-2022
+    env:
+      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+    steps:
+      - run: git config --global core.autocrlf false
+
+      - name: Checkout git repo
+        uses: actions/checkout@v4
+
+      - name: Setup & Build
+        uses: ./actions/setup_and_build
+        with:
+          cache_suffix: 'windows_x64'
+
+        # we want to test on all platforms since some are testing the rendered menus (and are dependent on the platform)
+      - name: Unit Test
+        run: yarn test
 
-      - name: Remove unpacked files
+      - name: Build but do not publish
+        # we want this to run always, except on "push" to "master"
+        if: ${{ env.SHOULD_PUBLISH == 'false' }}
+        run: yarn build-release
+
+      - name: Upload artefacts
+        # we want this to run always, except on "push" to "master"
+        if: ${{ env.SHOULD_PUBLISH == 'false' }}
+        uses: ./actions/upload_prod_artefacts
+        with:
+          upload_prefix: ${{ runner.os }}-${{ runner.arch }}
+
+      - name: Build & publish
+        # we want this to run only when on "push" to "master"
+        if: ${{ env.SHOULD_PUBLISH == 'true' }}
+        run: yarn build-release-publish # No other args needed for windows publish
+
+  # We want a mac arm64 build, and according to this https://github.com/actions/runner-images#available-images macos-14 is always arm64
+  # macos-14 is disabled for now as we hit our free tier limit for macos builds
+  build_macos_x64:
+    runs-on: macos-12
+    env:
+      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      MAC_CERTIFICATE: ${{ secrets.MAC_CERTIFICATE }}
+      MAC_CERTIFICATE_PASSWORD: ${{ secrets.MAC_CERTIFICATE_PASSWORD }}
+      SIGNING_APPLE_ID: ${{ secrets.SIGNING_APPLE_ID }}
+      SIGNING_APP_PASSWORD: ${{ secrets.SIGNING_APP_PASSWORD }}
+      SIGNING_TEAM_ID: ${{ secrets.SIGNING_TEAM_ID }}
+    steps:
+      - run: git config --global core.autocrlf false
+
+      - name: Checkout git repo
+        uses: actions/checkout@v4
+
+      - name: Setup & Build
+        uses: ./actions/setup_and_build
+        with:
+          cache_suffix: 'macos_x64'
+
+        # we want to test on all platforms since some are testing the rendered menus (and are dependent on the platform)
+      - name: Unit Test
+        run: yarn test
+
+      - name: Build but do not publish
+        # we want this to run always, except on "push" to "master"
+        if: ${{ env.SHOULD_PUBLISH == 'false' }}
         run: |
-          ls -d -- */ | xargs -I{} echo "Removing {}"
-          ls -d -- */ | xargs -I{} rm -rf {}
-        shell: bash
-        working-directory: ./release/
-
-      - name: Remaining files
-        run: ls .
-        shell: bash
-        working-directory: ./release/
-
-      - name: Upload Production Artifacts
-        uses: actions/upload-artifact@v4
+          source ./build/setup-mac-certificate.sh
+          yarn build-release --config.mac.bundleVersion=${{ github.ref }}
+
+      - name: Upload artefacts
+        # we want this to run always, except on "push" to "master"
+        if: ${{ env.SHOULD_PUBLISH == 'false' }}
+        uses: ./actions/upload_prod_artefacts
         with:
-          name: ${{ runner.os }}-${{ runner.arch }}-production
-          path: release
+          upload_prefix: ${{ runner.os }}-${{ runner.arch }}
+
+      - name: Build & publish
+        # we want this to run only when on "push" to "master"
+        if: ${{ env.SHOULD_PUBLISH == 'true' }}
+        run: |
+          source ./build/setup-mac-certificate.sh
+          yarn build-release-publish --config.mac.bundleVersion=${{ github.ref }}
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
deleted file mode 100644
index ca5779a5c50542d8de75fee757d1382e73a63837..0000000000000000000000000000000000000000
--- a/.github/workflows/pull-request.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-# This script will run tests anytime a pull request is added
-name: Session Test
-
-on:
-  pull_request:
-    branches:
-      - clearnet
-      - unstable
-      - 'release/**'
-      - 'ci/**'
-
-concurrency:
-  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
-  cancel-in-progress: true
-
-jobs:
-  build:
-    runs-on: ${{ matrix.os }}
-    strategy:
-      fail-fast: false
-      matrix:
-        # We want a mac arm64 build, and according to this https://github.com/actions/runner-images#available-images macos-14 is always arm64
-        # macos-14 is disabled for now as we hit our free tier limit for macos builds
-        os: [windows-2022, ubuntu-20.04, macos-12]
-    env:
-      SIGNAL_ENV: production
-      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-    steps:
-      - run: git config --global core.autocrlf false
-
-      - name: Checkout git repo
-        uses: actions/checkout@v3
-
-      - name: Setup & Build
-        uses: ./actions/setup_and_build
-
-      - name: Lint Files
-        # no need to lint files on all platforms. Just do it once on the quicker one
-        if: runner.os == 'Linux'
-        run: yarn lint-full
-
-      - name: Enforce yarn.lock has no duplicates
-        uses: ./actions/deduplicate_fail
-
-      - name: Unit Test
-        run: yarn test
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 4d5cfe22bd44fdb5b7c29f658a7e8ec26e3ee019..0000000000000000000000000000000000000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-# This script will build binaries and publish a draft on github release page with the the tag v[package-version]
-name: Session Draft Release
-
-on:
-  push:
-    branches:
-      - master
-
-jobs:
-  build:
-    runs-on: ${{ matrix.os }}
-    strategy:
-      fail-fast: false
-      matrix:
-        os: [windows-2022, ubuntu-20.04, macos-12]
-    env:
-      SIGNAL_ENV: production
-      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-    steps:
-      - run: git config --global core.autocrlf false
-
-      - name: Checkout git repo
-        uses: actions/checkout@v3
-
-      - name: Setup & Build
-        uses: ./actions/setup_and_build
-
-      - name: Build windows production binaries
-        if: runner.os == 'Windows'
-        run: node_modules\.bin\electron-builder --config.extraMetadata.environment=%SIGNAL_ENV% --publish=always
-
-      - name: Build mac production binaries
-        if: runner.os == 'macOS'
-        run: |
-          source ./build/setup-mac-certificate.sh
-          $(yarn bin)/electron-builder --config.extraMetadata.environment=$SIGNAL_ENV --config.mac.bundleVersion=${{ github.ref }} --publish=always
-        env:
-          MAC_CERTIFICATE: ${{ secrets.MAC_CERTIFICATE }}
-          MAC_CERTIFICATE_PASSWORD: ${{ secrets.MAC_CERTIFICATE_PASSWORD }}
-          SIGNING_APPLE_ID: ${{ secrets.SIGNING_APPLE_ID }}
-          SIGNING_APP_PASSWORD: ${{ secrets.SIGNING_APP_PASSWORD }}
-          SIGNING_TEAM_ID: ${{ secrets.SIGNING_TEAM_ID }}
-
-      - name: Build linux production binaries
-        if: runner.os == 'Linux'
-        run: |
-          sudo apt-get install -y rpm
-          yarn build-release-publish
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 727f3db973715b8dc29de9a375440edc6461303f..fc2c480492173bf78d3ab3bedf94c27e7f15827c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -274,3 +274,5 @@ You can build a production binary by running the following:
 yarn build-everything
 yarn build-release
 ```
+
+On linux, you can change in package.json `"target": ["deb"],` to any of the [electron-builder targets](https://www.electron.build/linux#target) to build for another target.
diff --git a/INTERNALBUILDS.md b/INTERNALBUILDS.md
index c246e97906a70feb9bbb87f9f5efa7a35fd981c3..8ab1b3db4adf43b9d77d583c5361ac15ccd6001d 100644
--- a/INTERNALBUILDS.md
+++ b/INTERNALBUILDS.md
@@ -146,3 +146,5 @@ yarn build-release
 ```
 
 The binaries will be placed inside the `release/` folder.
+
+On linux, you can change in package.json `"target": ["deb"],` to any of the [electron-builder targets](https://www.electron.build/linux#target) to build for another target.
diff --git a/actions/setup_and_build/action.yml b/actions/setup_and_build/action.yml
index 21e63ef33f667e4f231747eadb6051cc2d0bde4e..5c51a51464e90272d3704c357b18aa2dfb91fd6a 100644
--- a/actions/setup_and_build/action.yml
+++ b/actions/setup_and_build/action.yml
@@ -1,29 +1,25 @@
-
 name: 'Setup and build'
 description: 'Setup and build Session Desktop'
+inputs:
+  cache_suffix:
+    description: 'the package we are currently building (used as key for the cached node_modules)'
+    required: true
+
 runs:
   using: 'composite'
   steps:
     - name: Install node
-      uses: actions/setup-node@v3
+      uses: actions/setup-node@v4
       with:
         node-version-file: '.nvmrc'
 
-    - uses: actions/setup-python@v4
+    - uses: actions/setup-python@v5
       with:
         python-version: '3.11'
 
-    - name: Cache Desktop node_modules
-      id: cache-desktop-modules
-      uses: actions/cache@v3
-      if: runner.os != 'Windows'
-      with:
-        path: node_modules
-        key: ${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package.json', 'yarn.lock', 'patches/**') }}
-
     # Not having this will break the windows build because the PATH won't be set by msbuild.
     - name: Add msbuild to PATH
-      uses: microsoft/setup-msbuild@v1.3.1
+      uses: microsoft/setup-msbuild@v2
       if: runner.os == 'Windows'
 
     - name: Setup node for windows
@@ -32,11 +28,24 @@ runs:
       run: |
         yarn global add node-gyp@latest
 
+    - uses: actions/cache/restore@v4
+      id: cache-desktop-modules
+      with:
+        path: node_modules
+        key: ${{ runner.os }}-${{ runner.arch }}-${{ inputs.cache_suffix }}-${{ hashFiles('package.json', 'yarn.lock', 'patches/**') }}
+
     - name: Install dependencies
       shell: bash
       if: steps.cache-desktop-modules.outputs.cache-hit != 'true'
       run: yarn install --frozen-lockfile --network-timeout 600000
 
+    - uses: actions/cache/save@v4
+      id: cache-desktop-modules-save
+      if: runner.os != 'Windows'
+      with:
+        path: node_modules
+        key: ${{ runner.os }}-${{ runner.arch }}-${{ inputs.cache_suffix }}-${{ hashFiles('package.json', 'yarn.lock', 'patches/**') }}
+
     - name: Generate and concat files
       shell: bash
       run: yarn build-everything
diff --git a/actions/upload_prod_artefacts/action.yml b/actions/upload_prod_artefacts/action.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2e9542f925f8144a3f19457fafb4870cef52a2ec
--- /dev/null
+++ b/actions/upload_prod_artefacts/action.yml
@@ -0,0 +1,27 @@
+name: 'Upload production artefact (not publish)'
+description: 'Upload production artefact (not publish)'
+inputs:
+  upload_prefix:
+    description: 'upload name prefix'
+    required: true
+
+runs:
+  using: 'composite'
+  steps:
+    - name: Remove unpacked files
+      run: |
+        ls -d -- */ | xargs -I{} echo "Removing {}"
+        ls -d -- */ | xargs -I{} rm -rf {}
+      shell: bash
+      working-directory: ./release/
+
+    - name: Remaining files
+      run: ls .
+      shell: bash
+      working-directory: ./release/
+
+    - name: Upload Production Artifacts
+      uses: actions/upload-artifact@v4
+      with:
+        name: ${{ inputs.upload_prefix }}-production
+        path: release
diff --git a/build/updateLocalConfig.js b/build/updateLocalConfig.js
index 7fbbe4df1ee3adaa6e8301c2cdd1e201dc582ac4..3691a54cf0f699a1cbcfbd0850a120d6fcf14a2b 100644
--- a/build/updateLocalConfig.js
+++ b/build/updateLocalConfig.js
@@ -3,7 +3,7 @@ var _ = require('lodash');
 var execSync = require('child_process').execSync;
 
 const updateLocalConfig = () => {
-  var environment = process.env.SIGNAL_ENV || 'production';
+  var environment = 'production';
   var configPath = `config/local-${environment}.json`;
   var localConfig;
 
diff --git a/package.json b/package.json
index 79cc87ec9705e518bd9352d655c2580538c17832..5c6fbc49fed3ed3296a855d87ef3b3da319c0116 100644
--- a/package.json
+++ b/package.json
@@ -51,19 +51,9 @@
     "format-full": "prettier --list-different --write \"*.{css,js,json,scss,ts,tsx}\" \"./**/*.{css,js,json,scss,ts,tsx}\"",
     "start-prod-test": "cross-env NODE_ENV=production NODE_APP_INSTANCE=$MULTI electron .",
     "test": "mocha",
-    "build-release": "run-script-os",
-    "build-release-non-linux": "yarn build-everything && cross-env SIGNAL_ENV=production electron-builder --config.extraMetadata.environment=production --publish=never --config.directories.output=release",
-    "build-release:win32": "yarn build-release-non-linux",
-    "build-release:macos": "yarn build-release-non-linux",
-    "build-release:linux": "yarn sedtoDeb; yarn build-release-non-linux && yarn sedtoAppImage && yarn build-release-non-linux && yarn sedtoDeb",
-    "build-release-publish": "run-script-os",
-    "build-release-publish-non-linux": "yarn build-everything && cross-env SIGNAL_ENV=production $(yarn bin)/electron-builder --config.extraMetadata.environment=$SIGNAL_ENV --publish=always",
-    "build-release-publish:win32": "yarn build-release-publish-non-linux",
-    "build-release-publish:macos": "yarn build-release-publish-non-linux",
-    "build-release-publish:linux": "yarn sedtoDeb; yarn build-release-publish-non-linux && yarn sedtoAppImage && yarn build-release-publish-non-linux && yarn sedtoDeb",
-    "appImage": "yarn sedtoAppImage; yarn build-release-non-linux; yarn sedtoDeb",
-    "sedtoAppImage": "sed -i 's/\"target\": \\[\"deb\", \"rpm\", \"freebsd\"\\]/\"target\": \"AppImage\"/g' package.json",
-    "sedtoDeb": "sed -i 's/\"target\": \"AppImage\"/\"target\": \\[\"deb\", \"rpm\", \"freebsd\"\\]/g' package.json",
+    "build-release-base": "cross-env NODE_ENV=production electron-builder --config.extraMetadata.environment=production",
+    "build-release": "yarn build-release-base --publish=never --config.directories.output=release",
+    "build-release-publish": "yarn build-release-base --publish=always",
     "ready": "yarn dedup-yarn-lock --fail && yarn build-everything && yarn lint-full && yarn test",
     "postinstall": "yarn patch-package && yarn electron-builder install-app-deps",
     "update-git-info": "node ./build/updateLocalConfig.js",
@@ -208,7 +198,6 @@
     "postinstall-prepare": "^1.0.1",
     "prettier": "3.2.5",
     "protobufjs-cli": "^1.1.1",
-    "run-script-os": "^1.1.6",
     "sass": "^1.60.0",
     "sass-loader": "^13.2.2",
     "sinon": "9.0.2",
@@ -272,7 +261,7 @@
         "StartupWMClass": "Session"
       },
       "asarUnpack": "node_modules/spellchecker/vendor/hunspell_dictionaries",
-      "target": ["deb", "rpm", "freebsd"],
+      "target": ["deb"],
       "icon": "build/icon-linux.icns"
     },
     "asarUnpack": [
@@ -294,8 +283,8 @@
     "files": [
       "package.json",
       "config/default.json",
-      "config/${env.SIGNAL_ENV}.json",
-      "config/local-${env.SIGNAL_ENV}.json",
+      "config/production.json",
+      "config/local-production.json",
       "background.html",
       "about.html",
       "password.html",
diff --git a/ts/test/session/unit/updater/updater_test.ts b/ts/test/session/unit/updater/updater_test.ts
index 887faec20d38fabe5e0b58a9c2067a6e9b943f1f..c6880182dd8127c99d7a53253b8b8c27532676f6 100644
--- a/ts/test/session/unit/updater/updater_test.ts
+++ b/ts/test/session/unit/updater/updater_test.ts
@@ -6,14 +6,15 @@ import { isEmpty } from 'lodash';
 describe('Updater', () => {
   it.skip('isUpdateAvailable', () => {});
 
-  it('package.json target are correct', () => {
+  it('package.json target is correct', () => {
     const content = readFileSync(
       path.join(__dirname, '..', '..', '..', '..', '..', 'package.json')
     );
 
-    if (!content || isEmpty(content) || !content.includes('"target": ["deb", "rpm", "freebsd"],')) {
+    // the CI for building release relies on this being set to build the different targets.
+    if (!content || isEmpty(content) || !content.includes('"target": ["deb"],')) {
       throw new Error(
-        'Content empty or does not contain the target on a single line. They have to be for the linux appImage build to pass.'
+        'Content empty or does not contain the target on a single line. They have to be for the linux CI builds to pass.'
       );
     }
   });
diff --git a/yarn.lock b/yarn.lock
index 7aa704da91479c203c98227f94dd140674cfd5bb..ba5e93eb0bb1e93a490a388828b2e7f46ea8e5d2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6678,11 +6678,6 @@ run-parallel@^1.1.9:
   dependencies:
     queue-microtask "^1.2.2"
 
-run-script-os@^1.1.6:
-  version "1.1.6"
-  resolved "https://registry.yarnpkg.com/run-script-os/-/run-script-os-1.1.6.tgz#8b0177fb1b54c99a670f95c7fdc54f18b9c72347"
-  integrity sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==
-
 safe-array-concat@^1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb"