diff --git a/.gitlab/ci/memory.gitlab-ci.yml b/.gitlab/ci/memory.gitlab-ci.yml
index f3ad8f81da5d1652589d43ba6cea07bfa571a730..9234b116ff87b7bbc49b385b0799a83191857a05 100644
--- a/.gitlab/ci/memory.gitlab-ci.yml
+++ b/.gitlab/ci/memory.gitlab-ci.yml
@@ -4,6 +4,12 @@
     - .rails-cache
     - .default-before_script
     - .memory:rules
+  variables:
+    METRICS_FILE: "metrics.txt"
+  artifacts:
+    reports:
+      metrics: "${METRICS_FILE}"
+    expire_in: 31d
 
 memory-static:
   extends: .only-code-memory-job-base
@@ -11,24 +17,25 @@ memory-static:
   needs: ["setup-test-env"]
   variables:
     SETUP_DB: "false"
+    MEMORY_BUNDLE_MEM_FILE: "tmp/memory_bundle_mem.txt"
+    MEMORY_BUNDLE_OBJECTS_FILE: "tmp/memory_bundle_objects.txt"
   script:
     # Uses two different reports from the 'derailed_benchmars' gem.
 
     # Loads each of gems in the Gemfile and checks how much memory they consume when they are required.
     # 'derailed_benchmarks' internally uses 'get_process_mem'
-    - bundle exec derailed bundle:mem > tmp/memory_bundle_mem.txt
-    - scripts/generate-gems-size-metrics-static tmp/memory_bundle_mem.txt >> 'tmp/memory_metrics.txt'
+    - bundle exec derailed bundle:mem > "${MEMORY_BUNDLE_MEM_FILE}"
+    - scripts/generate-gems-size-metrics-static "${MEMORY_BUNDLE_MEM_FILE}" >> "${METRICS_FILE}"
 
     # Outputs detailed information about objects created while gems are loaded.
     # 'derailed_benchmarks' internally uses 'memory_profiler'
-    - bundle exec derailed bundle:objects > tmp/memory_bundle_objects.txt
-    - scripts/generate-gems-memory-metrics-static tmp/memory_bundle_objects.txt >> 'tmp/memory_metrics.txt'
+    - bundle exec derailed bundle:objects > "${MEMORY_BUNDLE_OBJECTS_FILE}"
+    - scripts/generate-gems-memory-metrics-static "${MEMORY_BUNDLE_OBJECTS_FILE}" >> "${METRICS_FILE}"
   artifacts:
     paths:
-      - tmp/memory_*.txt
-    reports:
-      metrics: tmp/memory_metrics.txt
-    expire_in: 31d
+      - "${METRICS_FILE}"
+      - "${MEMORY_BUNDLE_MEM_FILE}"
+      - "${MEMORY_BUNDLE_OBJECTS_FILE}"
 
 # Show memory usage caused by invoking require per gem.
 # Unlike `memory-static`, it hits the app with one request to ensure that any last minute require-s have been called.
@@ -44,12 +51,11 @@ memory-on-boot:
     NODE_ENV: "production"
     RAILS_ENV: "production"
     SETUP_DB: "true"
+    MEMORY_ON_BOOT_FILE: "tmp/memory_on_boot.txt"
   script:
-    - PATH_TO_HIT="/users/sign_in" CUT_OFF=0.3 bundle exec derailed exec perf:mem >> 'tmp/memory_on_boot.txt'
-    - scripts/generate-memory-metrics-on-boot tmp/memory_on_boot.txt >> 'tmp/memory_on_boot_metrics.txt'
+    - PATH_TO_HIT="/users/sign_in" CUT_OFF=0.3 bundle exec derailed exec perf:mem >> "${MEMORY_ON_BOOT_FILE}"
+    - scripts/generate-memory-metrics-on-boot "${MEMORY_ON_BOOT_FILE}" >> "${METRICS_FILE}"
   artifacts:
     paths:
-      - tmp/memory_*.txt
-    reports:
-      metrics: tmp/memory_on_boot_metrics.txt
-    expire_in: 31d
+      - "${METRICS_FILE}"
+      - "${MEMORY_ON_BOOT_FILE}"
diff --git a/scripts/utils.sh b/scripts/utils.sh
index d2e8c151438348be58a1fa3792b263f170ce0166..faabc1519638905a9eafb16f143e758c7751c647 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -60,7 +60,7 @@ function setup_db_user_only() {
 
 function setup_db() {
   run_timed_command "setup_db_user_only"
-  run_timed_command "bundle exec rake db:drop db:create db:structure:load db:migrate gitlab:db:setup_ee"
+  run_timed_command_with_metric "bundle exec rake db:drop db:create db:structure:load db:migrate gitlab:db:setup_ee" "setup_db"
 }
 
 function install_api_client_dependencies_with_apk() {
@@ -78,15 +78,27 @@ function install_tff_gem() {
 
 function run_timed_command() {
   local cmd="${1}"
+  local metric_name="${2}"
+  local timed_metric_file
   local start=$(date +%s)
+
   echosuccess "\$ ${cmd}"
   eval "${cmd}"
+
   local ret=$?
   local end=$(date +%s)
   local runtime=$((end-start))
 
   if [[ $ret -eq 0 ]]; then
     echosuccess "==> '${cmd}' succeeded in ${runtime} seconds."
+
+    if [[ -n "${metric_name}" ]]; then
+      timed_metric_file=$(timed_metric_file $metric_name)
+      echo "# TYPE ${metric_name} gauge" > "${timed_metric_file}"
+      echo "# UNIT ${metric_name} seconds" >> "${timed_metric_file}"
+      echo "${metric_name} ${runtime}" >> "${timed_metric_file}"
+    fi
+
     return 0
   else
     echoerr "==> '${cmd}' failed (${ret}) in ${runtime} seconds."
@@ -94,6 +106,26 @@ function run_timed_command() {
   fi
 }
 
+function run_timed_command_with_metric() {
+  local cmd="${1}"
+  local metric_name="${2}"
+  local metrics_file=${METRICS_FILE:-metrics.txt}
+
+  run_timed_command "${cmd}" "${metric_name}"
+
+  local ret=$?
+
+  cat $(timed_metric_file $metric_name) >> "${metrics_file}"
+
+  return $ret
+}
+
+function timed_metric_file() {
+  local metric_name="${1}"
+
+  echo "$(pwd)/tmp/duration_${metric_name}.txt"
+}
+
 function echoerr() {
   local header="${2}"