diff --git a/config/projects/gitlab.rb b/config/projects/gitlab.rb
index 7023dd671a915530ad3d515a964dadd8e78ac8e6_Y29uZmlnL3Byb2plY3RzL2dpdGxhYi5yYg==..b00b59e38cd30187cefa6e7cb94754f346d2a87f_Y29uZmlnL3Byb2plY3RzL2dpdGxhYi5yYg== 100644
--- a/config/projects/gitlab.rb
+++ b/config/projects/gitlab.rb
@@ -97,7 +97,6 @@
 end
 
 dependency 'cacerts'
-dependency 'jemalloc'
 dependency 'redis'
 dependency 'nginx'
 dependency 'mixlib-log'
diff --git a/config/software/jemalloc.rb b/config/software/jemalloc.rb
index 7023dd671a915530ad3d515a964dadd8e78ac8e6_Y29uZmlnL3NvZnR3YXJlL2plbWFsbG9jLnJi..b00b59e38cd30187cefa6e7cb94754f346d2a87f_Y29uZmlnL3NvZnR3YXJlL2plbWFsbG9jLnJi 100644
--- a/config/software/jemalloc.rb
+++ b/config/software/jemalloc.rb
@@ -53,9 +53,7 @@
   autogen_command << (OhaiHelper.arm64? ? '--with-lg-page=16' : '--with-lg-page=12')
 
   command autogen_command.join(' '), env: env
-  make "-j #{workers} build_lib", env: env
-  make 'install_lib', env: env
-  make 'install_bin', env: env
+  make "-j #{workers} install", env: env
 end
 
 project.exclude "embedded/bin/jemalloc-config"
diff --git a/config/software/ruby.rb b/config/software/ruby.rb
index 7023dd671a915530ad3d515a964dadd8e78ac8e6_Y29uZmlnL3NvZnR3YXJlL3J1YnkucmI=..b00b59e38cd30187cefa6e7cb94754f346d2a87f_Y29uZmlnL3NvZnR3YXJlL3J1YnkucmI= 100644
--- a/config/software/ruby.rb
+++ b/config/software/ruby.rb
@@ -35,6 +35,7 @@
 # Needed for chef_gem installs of (e.g.) nokogiri on upgrades -
 # they expect to see our libiconv instead of a system version.
 dependency 'libiconv'
+dependency 'jemalloc'
 
 version('2.7.5') { source sha256: '2755b900a21235b443bb16dadd9032f784d4a88f143d852bc5d154f22b8781f1' }
 
@@ -54,6 +55,8 @@
 
 build do
   env['CFLAGS'] << ' -fno-omit-frame-pointer'
+  # Fix for https://bugs.ruby-lang.org/issues/18409. This can be removed with Ruby 3.0+.
+  env['LDFLAGS'] << ' -Wl,--no-as-needed'
 
   # disable libpath in mkmf across all platforms, it trolls omnibus and
   # breaks the postgresql cookbook.  i'm not sure why ruby authors decided
@@ -80,6 +83,7 @@
 
   configure_command = ['--with-out-ext=dbm,readline',
                        '--enable-shared',
+                       '--with-jemalloc',
                        '--disable-install-doc',
                        '--without-gmp',
                        '--without-gdbm',
diff --git a/doc/settings/memory_constrained_envs.md b/doc/settings/memory_constrained_envs.md
index 7023dd671a915530ad3d515a964dadd8e78ac8e6_ZG9jL3NldHRpbmdzL21lbW9yeV9jb25zdHJhaW5lZF9lbnZzLm1k..b00b59e38cd30187cefa6e7cb94754f346d2a87f_ZG9jL3NldHRpbmdzL21lbW9yeV9jb25zdHJhaW5lZF9lbnZzLm1k 100644
--- a/doc/settings/memory_constrained_envs.md
+++ b/doc/settings/memory_constrained_envs.md
@@ -215,7 +215,6 @@
 }
 
 gitaly['env'] = {
-  'LD_PRELOAD' => '/opt/gitlab/embedded/lib/libjemalloc.so',
   'MALLOC_CONF' => 'dirty_decay_ms:1000,muzzy_decay_ms:1000'
 }
 ```
@@ -271,7 +270,6 @@
      }
    ]
    gitaly['env'] = {
-     'LD_PRELOAD' => '/opt/gitlab/embedded/lib/libjemalloc.so',
      'MALLOC_CONF' => 'dirty_decay_ms:1000,muzzy_decay_ms:1000',
      'GITALY_COMMAND_SPAWN_MAX_PARALLEL' => '2'
    }
diff --git a/files/gitlab-cookbooks/gitlab/attributes/default.rb b/files/gitlab-cookbooks/gitlab/attributes/default.rb
index 7023dd671a915530ad3d515a964dadd8e78ac8e6_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvYXR0cmlidXRlcy9kZWZhdWx0LnJi..b00b59e38cd30187cefa6e7cb94754f346d2a87f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvYXR0cmlidXRlcy9kZWZhdWx0LnJi 100644
--- a/files/gitlab-cookbooks/gitlab/attributes/default.rb
+++ b/files/gitlab-cookbooks/gitlab/attributes/default.rb
@@ -80,7 +80,6 @@
   'SSL_CERT_DIR' => "#{node['package']['install-dir']}/embedded/ssl/certs/",
   'SSL_CERT_FILE' => "#{node['package']['install-dir']}/embedded/ssl/cert.pem"
 }
-default['gitlab']['gitlab-rails']['enable_jemalloc'] = true
 
 default['gitlab']['gitlab-rails']['internal_api_url'] = nil
 default['gitlab']['gitlab-rails']['uploads_directory'] = "/var/opt/gitlab/gitlab-rails/uploads"
diff --git a/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb b/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb
index 7023dd671a915530ad3d515a964dadd8e78ac8e6_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvcmVjaXBlcy9naXRsYWItcmFpbHMucmI=..b00b59e38cd30187cefa6e7cb94754f346d2a87f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvcmVjaXBlcy9naXRsYWItcmFpbHMucmI= 100644
--- a/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb
+++ b/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb
@@ -423,8 +423,6 @@
 gitlab_relative_url = node['gitlab']['gitlab-rails']['gitlab_relative_url']
 rails_env['RAILS_RELATIVE_URL_ROOT'] = gitlab_relative_url if gitlab_relative_url
 
-rails_env['LD_PRELOAD'] = "/opt/gitlab/embedded/lib/libjemalloc.so" if node['gitlab']['gitlab-rails']['enable_jemalloc']
-
 rails_env['BUNDLE_GEMFILE'] = GitlabRailsEnvHelper.bundle_gemfile(gitlab_rails_source_dir)
 
 env_dir File.join(gitlab_rails_static_etc_dir, 'env') do
diff --git a/files/gitlab-cookbooks/monitoring/attributes/default.rb b/files/gitlab-cookbooks/monitoring/attributes/default.rb
index 7023dd671a915530ad3d515a964dadd8e78ac8e6_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL2F0dHJpYnV0ZXMvZGVmYXVsdC5yYg==..b00b59e38cd30187cefa6e7cb94754f346d2a87f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9tb25pdG9yaW5nL2F0dHJpYnV0ZXMvZGVmYXVsdC5yYg== 100644
--- a/files/gitlab-cookbooks/monitoring/attributes/default.rb
+++ b/files/gitlab-cookbooks/monitoring/attributes/default.rb
@@ -115,8 +115,6 @@
 default['monitoring']['gitlab-exporter']['elasticsearch_url'] = nil
 default['monitoring']['gitlab-exporter']['elasticsearch_authorization'] = nil
 default['monitoring']['gitlab-exporter']['env'] = {
-  # See https://gitlab.com/gitlab-org/gitlab/-/issues/297241
-  'LD_PRELOAD' => '/opt/gitlab/embedded/lib/libjemalloc.so',
   'MALLOC_CONF' => 'dirty_decay_ms:0,muzzy_decay_ms:0',
   'RUBY_GC_HEAP_INIT_SLOTS' => 80000,
   'RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO' => 0.055,
diff --git a/files/gitlab-cookbooks/package/libraries/deprecations.rb b/files/gitlab-cookbooks/package/libraries/deprecations.rb
index 7023dd671a915530ad3d515a964dadd8e78ac8e6_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9kZXByZWNhdGlvbnMucmI=..b00b59e38cd30187cefa6e7cb94754f346d2a87f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9kZXByZWNhdGlvbnMucmI= 100644
--- a/files/gitlab-cookbooks/package/libraries/deprecations.rb
+++ b/files/gitlab-cookbooks/package/libraries/deprecations.rb
@@ -318,6 +318,12 @@
             deprecation: '15.5',
             removal: '16.0', # https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/7072
             note: "Starting with GitLab 16.0, Praefect DB metrics will no longer be available on `/metrics` and must be scraped from `/db_metrics`."
+          },
+          {
+            config_keys: %w(gitlab gitlab-rails enable_jemalloc),
+            deprecation: '15.5',
+            removal: '15.5',
+            note: "Starting with GitLab 15.5, jemalloc is compiled in with the Ruby interpreter and can no longer be disabled."
           }
         ]
 
diff --git a/spec/chef/cookbooks/gitlab/recipes/gitlab-rails_spec.rb b/spec/chef/cookbooks/gitlab/recipes/gitlab-rails_spec.rb
index 7023dd671a915530ad3d515a964dadd8e78ac8e6_c3BlYy9jaGVmL2Nvb2tib29rcy9naXRsYWIvcmVjaXBlcy9naXRsYWItcmFpbHNfc3BlYy5yYg==..b00b59e38cd30187cefa6e7cb94754f346d2a87f_c3BlYy9jaGVmL2Nvb2tib29rcy9naXRsYWIvcmVjaXBlcy9naXRsYWItcmFpbHNfc3BlYy5yYg== 100644
--- a/spec/chef/cookbooks/gitlab/recipes/gitlab-rails_spec.rb
+++ b/spec/chef/cookbooks/gitlab/recipes/gitlab-rails_spec.rb
@@ -17,7 +17,6 @@
       'PYTHONPATH' => '/opt/gitlab/embedded/lib/python3.9/site-packages',
       'EXECJS_RUNTIME' => 'Disabled',
       'TZ' => ':/etc/localtime',
-      'LD_PRELOAD' => '/opt/gitlab/embedded/lib/libjemalloc.so',
       'SSL_CERT_DIR' => '/opt/gitlab/embedded/ssl/certs/',
       'SSL_CERT_FILE' => '/opt/gitlab/embedded/ssl/cert.pem'
     }
@@ -465,18 +464,6 @@
         )
       end
     end
-
-    context 'when jemalloc is disabled' do
-      before do
-        stub_gitlab_rb(gitlab_rails: { enable_jemalloc: false })
-      end
-
-      it 'creates necessary env variable files' do
-        vars = default_vars.dup
-        vars.delete("LD_PRELOAD")
-        expect(chef_run).to create_env_dir('/opt/gitlab/etc/gitlab-rails/env').with_variables(vars)
-      end
-    end
   end
 
   describe "with symlinked templates" do
diff --git a/spec/chef/cookbooks/monitoring/recipes/gitlab-exporter_spec.rb b/spec/chef/cookbooks/monitoring/recipes/gitlab-exporter_spec.rb
index 7023dd671a915530ad3d515a964dadd8e78ac8e6_c3BlYy9jaGVmL2Nvb2tib29rcy9tb25pdG9yaW5nL3JlY2lwZXMvZ2l0bGFiLWV4cG9ydGVyX3NwZWMucmI=..b00b59e38cd30187cefa6e7cb94754f346d2a87f_c3BlYy9jaGVmL2Nvb2tib29rcy9tb25pdG9yaW5nL3JlY2lwZXMvZ2l0bGFiLWV4cG9ydGVyX3NwZWMucmI= 100644
--- a/spec/chef/cookbooks/monitoring/recipes/gitlab-exporter_spec.rb
+++ b/spec/chef/cookbooks/monitoring/recipes/gitlab-exporter_spec.rb
@@ -4,7 +4,6 @@
   let(:chef_run) { ChefSpec::SoloRunner.new(step_into: %w(runit_service)).converge('gitlab::default') }
   let(:default_env_vars) do
     {
-      'LD_PRELOAD' => '/opt/gitlab/embedded/lib/libjemalloc.so',
       'MALLOC_CONF' => 'dirty_decay_ms:0,muzzy_decay_ms:0',
       'RUBY_GC_HEAP_INIT_SLOTS' => 80000,
       'RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO' => 0.055,