diff --git a/app/assets/javascripts/organizations/mock_data.js b/app/assets/javascripts/organizations/mock_data.js
index 56aa0ea28a928028aa93623c15c57df2e49c2906..29898708a41302ddbe698b640f4db67328c0fdd4 100644
--- a/app/assets/javascripts/organizations/mock_data.js
+++ b/app/assets/javascripts/organizations/mock_data.js
@@ -4,6 +4,13 @@
 // https://gitlab.com/gitlab-org/gitlab/-/issues/420777
 // https://gitlab.com/gitlab-org/gitlab/-/issues/421441
 
+export const defaultOrganization = {
+  id: 1,
+  name: 'Default',
+  web_url: '/-/organizations/default',
+  avatar_url: null,
+};
+
 export const organizations = [
   {
     id: 'gid://gitlab/Organizations::Organization/1',
diff --git a/app/assets/javascripts/super_sidebar/components/organization_switcher.vue b/app/assets/javascripts/super_sidebar/components/organization_switcher.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7122f147d3e2c4f60a5e92f7f2b11f6abc5f1525
--- /dev/null
+++ b/app/assets/javascripts/super_sidebar/components/organization_switcher.vue
@@ -0,0 +1,144 @@
+<script>
+import { GlDisclosureDropdown, GlAvatar, GlIcon, GlLoadingIcon } from '@gitlab/ui';
+import getCurrentUserOrganizations from '~/organizations/shared/graphql/queries/organizations.query.graphql';
+import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { defaultOrganization } from '~/organizations/mock_data';
+import { s__ } from '~/locale';
+
+export default {
+  AVATAR_SHAPE_OPTION_RECT,
+  ITEM_LOADING: {
+    id: 'loading',
+    text: 'loading',
+    extraAttrs: { disabled: true, class: 'gl-shadow-none!' },
+  },
+  ITEM_EMPTY: {
+    id: 'empty',
+    text: s__('Organization|No organizations available to switch to.'),
+    extraAttrs: { disabled: true, class: 'gl-shadow-none! gl-text-secondary' },
+  },
+  i18n: {
+    currentOrganization: s__('Organization|Current organization'),
+    switchOrganizations: s__('Organization|Switch organizations'),
+  },
+  components: { GlDisclosureDropdown, GlAvatar, GlIcon, GlLoadingIcon },
+  data() {
+    return {
+      organizations: {},
+      dropdownShown: false,
+    };
+  },
+  apollo: {
+    organizations: {
+      query: getCurrentUserOrganizations,
+      update(data) {
+        return data.currentUser.organizations;
+      },
+      skip() {
+        return !this.dropdownShown;
+      },
+      error() {
+        this.organizations = {
+          nodes: [],
+          pageInfo: {},
+        };
+      },
+    },
+  },
+  computed: {
+    loading() {
+      return this.$apollo.queries.organizations.loading;
+    },
+    currentOrganization() {
+      // TODO - use `gon.current_organization` when backend supports it.
+      // https://gitlab.com/gitlab-org/gitlab/-/issues/437095
+      return defaultOrganization;
+    },
+    nodes() {
+      return this.organizations.nodes || [];
+    },
+    items() {
+      const currentOrganizationGroup = {
+        name: this.$options.i18n.currentOrganization,
+        items: [
+          {
+            id: this.currentOrganization.id,
+            text: this.currentOrganization.name,
+            href: this.currentOrganization.web_url,
+            avatarUrl: this.currentOrganization.avatar_url,
+          },
+        ],
+      };
+
+      if (this.loading || !this.dropdownShown) {
+        return [
+          currentOrganizationGroup,
+          {
+            name: this.$options.i18n.switchOrganizations,
+            items: [this.$options.ITEM_LOADING],
+          },
+        ];
+      }
+
+      const items = this.nodes
+        .map((node) => ({
+          id: getIdFromGraphQLId(node.id),
+          text: node.name,
+          href: node.webUrl,
+          avatarUrl: node.avatarUrl,
+        }))
+        .filter((item) => item.id !== this.currentOrganization.id);
+
+      return [
+        currentOrganizationGroup,
+        {
+          name: this.$options.i18n.switchOrganizations,
+          items: items.length ? items : [this.$options.ITEM_EMPTY],
+        },
+      ];
+    },
+  },
+  methods: {
+    onShown() {
+      this.dropdownShown = true;
+    },
+  },
+};
+</script>
+
+<template>
+  <gl-disclosure-dropdown :items="items" class="gl-display-block" @shown="onShown">
+    <template #toggle>
+      <button
+        class="organization-switcher-button gl-display-flex gl-align-items-center gl-gap-3 gl-p-3 gl-rounded-base gl-border-none gl-line-height-1 gl-w-full"
+        data-testid="toggle-button"
+      >
+        <gl-avatar
+          :size="24"
+          :shape="$options.AVATAR_SHAPE_OPTION_RECT"
+          :entity-id="currentOrganization.id"
+          :entity-name="currentOrganization.name"
+          :src="currentOrganization.avatar_url"
+        />
+        <span>{{ currentOrganization.name }}</span>
+        <gl-icon class="gl-button-icon gl-new-dropdown-chevron" name="chevron-down" />
+      </button>
+    </template>
+
+    <template #list-item="{ item }">
+      <gl-loading-icon v-if="item.id === $options.ITEM_LOADING.id" />
+      <span v-else-if="item.id === $options.ITEM_EMPTY.id">{{ item.text }}</span>
+      <div v-else class="gl-display-flex gl-align-items-center gl-gap-3">
+        <gl-avatar
+          :size="24"
+          :shape="$options.AVATAR_SHAPE_OPTION_RECT"
+          :entity-id="item.id"
+          :entity-name="item.text"
+          :src="item.avatarUrl"
+        />
+        <span>{{ item.text }}</span>
+      </div>
+    </template>
+  </gl-disclosure-dropdown>
+</template>
diff --git a/app/assets/javascripts/super_sidebar/components/user_bar.vue b/app/assets/javascripts/super_sidebar/components/user_bar.vue
index 3c8bf62ff5c55d9b96dd1b4fdd71d23797778c1c..794a8b2cea9c6039933bdc00fe57bf565dea10fe 100644
--- a/app/assets/javascripts/super_sidebar/components/user_bar.vue
+++ b/app/assets/javascripts/super_sidebar/components/user_bar.vue
@@ -6,6 +6,7 @@ import {
   createUserCountsManager,
   userCounts,
 } from '~/super_sidebar/user_counts_manager';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
 import BrandLogo from 'jh_else_ce/super_sidebar/components/brand_logo.vue';
 import { JS_TOGGLE_COLLAPSE_CLASS } from '../constants';
 import CreateMenu from './create_menu.vue';
@@ -35,6 +36,8 @@ export default {
     SuperSidebarToggle,
     BrandLogo,
     GlIcon,
+    OrganizationSwitcher: () =>
+      import(/* webpackChunkName: 'organization_switcher' */ './organization_switcher.vue'),
   },
   i18n: {
     issues: __('Issues'),
@@ -52,6 +55,7 @@ export default {
     GlTooltip: GlTooltipDirective,
     GlModal: GlModalDirective,
   },
+  mixins: [glFeatureFlagsMixin()],
   inject: ['isImpersonating'],
   props: {
     hasCollapseButton: {
@@ -149,6 +153,7 @@ export default {
         data-testid="stop-impersonation-btn"
       />
     </div>
+    <organization-switcher v-if="glFeatures.uiForOrganizations" />
     <div
       v-if="sidebarData.is_logged_in"
       class="gl-display-flex gl-justify-content-space-between gl-gap-2"
diff --git a/app/assets/stylesheets/framework/super_sidebar.scss b/app/assets/stylesheets/framework/super_sidebar.scss
index 0cb35bc117bc10d415f9b91a3ce0263ef0d9c9b3..4d0b22928cc1c8d77e95ea8d16a3d59735264175 100644
--- a/app/assets/stylesheets/framework/super_sidebar.scss
+++ b/app/assets/stylesheets/framework/super_sidebar.scss
@@ -231,6 +231,18 @@ $super-sidebar-transition-hint-duration: $super-sidebar-transition-duration / 4;
   .user-bar {
     background-color: var(--super-sidebar-user-bar-bg);
 
+    .organization-switcher-button {
+      background-color: transparent;
+      color: var(--super-sidebar-user-bar-button-color);
+
+      &:active,
+      &:hover,
+      &:focus {
+        background-color: var(--super-sidebar-user-bar-button-hover-bg);
+        color: var(--super-sidebar-user-bar-button-hover-color);
+      }
+    }
+
     .user-bar-dropdown-toggle {
       padding: $gl-spacing-scale-2;
       @include gl-border-none;
diff --git a/ee/spec/features/registrations/saas/invite_flow_spec.rb b/ee/spec/features/registrations/saas/invite_flow_spec.rb
index c0832f38d25ba28ccfeb4b2468febfc585cde7cd..3a0996e49410b53239b19ba543993f0151466bfa 100644
--- a/ee/spec/features/registrations/saas/invite_flow_spec.rb
+++ b/ee/spec/features/registrations/saas/invite_flow_spec.rb
@@ -55,7 +55,7 @@ def registers_from_invite(user:, group:)
     visit invite_path(invitation.raw_invite_token, invite_type: Emails::Members::INITIAL_INVITE)
 
     # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/438017
-    allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(103)
+    allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(102)
 
     fill_in_sign_up_form(user, invite: true)
   end
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index 6420b2561dcde22f2a4e0618c3c042ecf9f98f95..9d7e73ba1f232a3951a74b0699b8ce29433021ee 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -77,6 +77,7 @@ def add_gon_variables
       push_frontend_feature_flag(:source_editor_toolbar)
       push_frontend_feature_flag(:vscode_web_ide, current_user)
       push_frontend_feature_flag(:key_contacts_management, current_user)
+      push_frontend_feature_flag(:ui_for_organizations, current_user)
       # To be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/399248
       push_frontend_feature_flag(:remove_monitor_metrics)
       push_frontend_feature_flag(:custom_emoji)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d925ac87c1da8e5d054ece201b88c773deb8bc47..333b78b037def8ab01df5e6bfc7dca150a55c263 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -34232,6 +34232,9 @@ msgstr ""
 msgid "Organization|Create organization"
 msgstr ""
 
+msgid "Organization|Current organization"
+msgstr ""
+
 msgid "Organization|Frequently visited groups"
 msgstr ""
 
@@ -34256,6 +34259,9 @@ msgstr ""
 msgid "Organization|New organization"
 msgstr ""
 
+msgid "Organization|No organizations available to switch to."
+msgstr ""
+
 msgid "Organization|Org ID"
 msgstr ""
 
@@ -34319,6 +34325,9 @@ msgstr ""
 msgid "Organization|Select an organization"
 msgstr ""
 
+msgid "Organization|Switch organizations"
+msgstr ""
+
 msgid "Organization|Unable to fetch organizations. Reload the page to try again."
 msgstr ""
 
diff --git a/spec/features/nav/pinned_nav_items_spec.rb b/spec/features/nav/pinned_nav_items_spec.rb
index a2428048a1ad099091c35b4492ee32459c410d86..a1137536dd5052ee64a6e6a6d4ae4549f48a9cd4 100644
--- a/spec/features/nav/pinned_nav_items_spec.rb
+++ b/spec/features/nav/pinned_nav_items_spec.rb
@@ -170,6 +170,7 @@
 
   def add_pin(nav_item_title)
     nav_item = find("[data-testid=\"nav-item\"]", text: nav_item_title)
+    scroll_to(nav_item)
     nav_item.hover
     pin_button = nav_item.find("[data-testid=\"nav-item-pin\"]")
     pin_button.click
@@ -178,6 +179,7 @@ def add_pin(nav_item_title)
 
   def remove_pin(nav_item_title)
     nav_item = find("[data-testid=\"nav-item\"]", text: nav_item_title)
+    scroll_to(nav_item)
     nav_item.hover
     unpin_button = nav_item.find("[data-testid=\"nav-item-unpin\"]")
     unpin_button.click
diff --git a/spec/frontend/super_sidebar/components/organization_switcher_spec.js b/spec/frontend/super_sidebar/components/organization_switcher_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..094cb4baedb3c79df141ae6206ea6a5ae23b1a51
--- /dev/null
+++ b/spec/frontend/super_sidebar/components/organization_switcher_spec.js
@@ -0,0 +1,148 @@
+import { GlAvatar, GlDisclosureDropdown, GlLoadingIcon } from '@gitlab/ui';
+import VueApollo from 'vue-apollo';
+import Vue from 'vue';
+
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import OrganizationSwitcher from '~/super_sidebar/components/organization_switcher.vue';
+import {
+  defaultOrganization as currentOrganization,
+  organizations as nodes,
+  pageInfo,
+  pageInfoEmpty,
+} from '~/organizations/mock_data';
+import organizationsQuery from '~/organizations/shared/graphql/queries/organizations.query.graphql';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+
+Vue.use(VueApollo);
+
+describe('OrganizationSwitcher', () => {
+  let wrapper;
+  let mockApollo;
+
+  const [, secondOrganization, thirdOrganization] = nodes;
+
+  const organizations = {
+    nodes,
+    pageInfo,
+  };
+
+  const successHandler = jest.fn().mockResolvedValue({
+    data: {
+      currentUser: {
+        id: 'gid://gitlab/User/1',
+        organizations,
+      },
+    },
+  });
+
+  const createComponent = (handler = successHandler) => {
+    mockApollo = createMockApollo([[organizationsQuery, handler]]);
+
+    wrapper = mountExtended(OrganizationSwitcher, {
+      apolloProvider: mockApollo,
+    });
+  };
+
+  const findDropdownItemByIndex = (index) =>
+    wrapper.findAllByTestId('disclosure-dropdown-item').at(index);
+  const showDropdown = () => wrapper.findComponent(GlDisclosureDropdown).vm.$emit('shown');
+
+  afterEach(() => {
+    mockApollo = null;
+  });
+
+  it('renders disclosure dropdown with current organization selected', () => {
+    createComponent();
+
+    const toggleButton = wrapper.findByTestId('toggle-button');
+    const dropdownItem = findDropdownItemByIndex(0);
+
+    expect(toggleButton.text()).toContain(currentOrganization.name);
+    expect(toggleButton.findComponent(GlAvatar).props()).toMatchObject({
+      src: currentOrganization.avatar_url,
+      entityId: currentOrganization.id,
+      entityName: currentOrganization.name,
+    });
+    expect(dropdownItem.text()).toContain(currentOrganization.name);
+    expect(dropdownItem.findComponent(GlAvatar).props()).toMatchObject({
+      src: currentOrganization.avatar_url,
+      entityId: currentOrganization.id,
+      entityName: currentOrganization.name,
+    });
+  });
+
+  it('does not call GraphQL query', () => {
+    createComponent();
+
+    expect(successHandler).not.toHaveBeenCalled();
+  });
+
+  describe('when dropdown is shown', () => {
+    it('calls GraphQL query and renders organizations that are available to switch to', async () => {
+      createComponent();
+      showDropdown();
+
+      expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+
+      await waitForPromises();
+
+      expect(findDropdownItemByIndex(1).text()).toContain(secondOrganization.name);
+      expect(findDropdownItemByIndex(1).element.firstChild.getAttribute('href')).toBe(
+        secondOrganization.webUrl,
+      );
+      expect(findDropdownItemByIndex(1).findComponent(GlAvatar).props()).toMatchObject({
+        src: secondOrganization.avatarUrl,
+        entityId: getIdFromGraphQLId(secondOrganization.id),
+        entityName: secondOrganization.name,
+      });
+
+      expect(findDropdownItemByIndex(2).text()).toContain(thirdOrganization.name);
+      expect(findDropdownItemByIndex(2).element.firstChild.getAttribute('href')).toBe(
+        thirdOrganization.webUrl,
+      );
+      expect(findDropdownItemByIndex(2).findComponent(GlAvatar).props()).toMatchObject({
+        src: thirdOrganization.avatarUrl,
+        entityId: getIdFromGraphQLId(thirdOrganization.id),
+        entityName: thirdOrganization.name,
+      });
+    });
+
+    describe('when there are no organizations to switch to', () => {
+      beforeEach(async () => {
+        createComponent(
+          jest.fn().mockResolvedValue({
+            data: {
+              currentUser: {
+                id: 'gid://gitlab/User/1',
+                organizations: {
+                  nodes: [],
+                  pageInfo: pageInfoEmpty,
+                },
+              },
+            },
+          }),
+        );
+        showDropdown();
+        await waitForPromises();
+      });
+
+      it('renders empty message', () => {
+        expect(findDropdownItemByIndex(1).text()).toBe('No organizations available to switch to.');
+      });
+    });
+
+    describe('when there is an error fetching organizations', () => {
+      beforeEach(async () => {
+        createComponent(jest.fn().mockRejectedValue());
+        showDropdown();
+        await waitForPromises();
+      });
+
+      it('renders empty message', () => {
+        expect(findDropdownItemByIndex(1).text()).toBe('No organizations available to switch to.');
+      });
+    });
+  });
+});
diff --git a/spec/frontend/super_sidebar/components/user_bar_spec.js b/spec/frontend/super_sidebar/components/user_bar_spec.js
index 27d65f27007430b356b84b8854ed02da4bf2c523..fa2c6fdf1659928113957968fd83f6c927d1a632 100644
--- a/spec/frontend/super_sidebar/components/user_bar_spec.js
+++ b/spec/frontend/super_sidebar/components/user_bar_spec.js
@@ -9,16 +9,20 @@ import UserMenu from '~/super_sidebar/components/user_menu.vue';
 import SearchModal from '~/super_sidebar/components/global_search/components/global_search.vue';
 import BrandLogo from 'jh_else_ce/super_sidebar/components/brand_logo.vue';
 import MergeRequestMenu from '~/super_sidebar/components/merge_request_menu.vue';
+import OrganizationSwitcher from '~/super_sidebar/components/organization_switcher.vue';
 import UserBar from '~/super_sidebar/components/user_bar.vue';
 import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
 import waitForPromises from 'helpers/wait_for_promises';
 import { userCounts } from '~/super_sidebar/user_counts_manager';
+import { stubComponent } from 'helpers/stub_component';
 import { sidebarData as mockSidebarData, loggedOutSidebarData } from '../mock_data';
 import { MOCK_DEFAULT_SEARCH_OPTIONS } from './global_search/mock_data';
 
 describe('UserBar component', () => {
   let wrapper;
 
+  const OrganizationSwitcherStub = stubComponent(OrganizationSwitcher);
+
   const findCreateMenu = () => wrapper.findComponent(CreateMenu);
   const findUserMenu = () => wrapper.findComponent(UserMenu);
   const findIssuesCounter = () => wrapper.findByTestId('issues-shortcut-button');
@@ -30,6 +34,7 @@ describe('UserBar component', () => {
   const findSearchButton = () => wrapper.findByTestId('super-sidebar-search-button');
   const findSearchModal = () => wrapper.findComponent(SearchModal);
   const findStopImpersonationButton = () => wrapper.findByTestId('stop-impersonation-btn');
+  const findOrganizationSwitcher = () => wrapper.findComponent(OrganizationSwitcherStub);
 
   Vue.use(Vuex);
 
@@ -56,6 +61,9 @@ describe('UserBar component', () => {
         GlTooltip: createMockDirective('gl-tooltip'),
       },
       store,
+      stubs: {
+        OrganizationSwitcher: OrganizationSwitcherStub,
+      },
     });
   };
 
@@ -252,4 +260,22 @@ describe('UserBar component', () => {
       expect(findTodosCounter().exists()).toBe(false);
     });
   });
+
+  describe('when `ui_for_organizations` feature flag is enabled', () => {
+    it('renders `OrganizationSwitcher component', async () => {
+      createWrapper({ provideOverrides: { glFeatures: { uiForOrganizations: true } } });
+      await waitForPromises();
+
+      expect(findOrganizationSwitcher().exists()).toBe(true);
+    });
+  });
+
+  describe('when `ui_for_organizations` feature flag is disabled', () => {
+    it('renders `OrganizationSwitcher component', async () => {
+      createWrapper();
+      await waitForPromises();
+
+      expect(findOrganizationSwitcher().exists()).toBe(false);
+    });
+  });
 });