diff --git a/test-and-deploy.yml b/test-and-deploy.yml
index 29e800cf124990f759a23885f7a6fb21f232593e..c4c484380396ee138380f6b595dbc286f452bf10 100644
--- a/test-and-deploy.yml
+++ b/test-and-deploy.yml
@@ -1,5 +1,6 @@
 stages:
   - validation
+  - buildprod
   - build
   - prepare
   - test
@@ -28,6 +29,15 @@ stages:
     - .env
     - docker-compose.yml
 
+.artifact_paths_prod: &artifact_paths_prod
+  paths:
+    - config/
+    - drush/
+    - vendor/
+    - web/
+    - .ahoy.yml
+    - .env
+
 .artifact_paths: &artifact_paths
   paths:
     - .docker-init/
@@ -87,6 +97,41 @@ stages:
     reports:
       dotenv: validation.env
 
+.build-prod:
+  stage: buildprod
+  tags:
+    - default
+  cache:
+    <<: *cache_default
+    policy: pull-push
+  script: |
+    if [[ -n $SSH_PRIVATE_KEY ]]; then
+      eval $(ssh-agent -s)
+      echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
+      mkdir -p ~/.ssh
+      chmod 700 ~/.ssh
+      ssh-keyscan gitlab.lakedrops.com >> ~/.ssh/known_hosts
+      chmod 644 ~/.ssh/known_hosts
+      ssh git@gitlab.lakedrops.com
+    fi
+    if [[ -n $DOWNGRADE_COMPOSER ]]; then
+      composer self-update --$DOWNGRADE_COMPOSER;
+    fi
+    if [[ -n $GITLAB_ACCESS_TOKEN ]]; then
+      composer config -g gitlab-token.gitlab.lakedrops.com $GITLAB_ACCESS_TOKEN;
+    fi
+    composer install --no-interaction --no-progress --no-dev
+  artifacts:
+    name: build-prod
+    when: always
+    <<: *artifact_paths_prod
+  except:
+    refs:
+      - tags
+    variables:
+      - $CI_COMMIT_MESSAGE =~ /^Merge tag /i
+      - $CAE
+
 .build:
   stage: build
   tags: