diff --git a/Gemfile b/Gemfile
index ea521c7f19156471fe9ec5b529bff93e1fa2f4e0..088ce9a0aef729b8ecbcc92a744b78813d475635 100644
--- a/Gemfile
+++ b/Gemfile
@@ -465,3 +465,6 @@ gem 'grape_logging', '~> 1.7'
 
 # DNS Lookup
 gem 'net-dns', '~> 0.9.0'
+
+# Countries list
+gem 'countries', '~> 3.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index df572cbe0e0dbe4eacce4ee4619da96782bdb269..2d6d3d196d8e33b3355cd8dfb8311886e7f6462d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -167,6 +167,10 @@ GEM
     contracts (0.11.0)
     cork (0.3.0)
       colored2 (~> 3.1)
+    countries (3.0.0)
+      i18n_data (~> 0.8.0)
+      sixarm_ruby_unaccent (~> 1.1)
+      unicode_utils (~> 1.4)
     crack (0.4.3)
       safe_yaml (~> 1.0.0)
     crass (1.0.4)
@@ -485,6 +489,7 @@ GEM
     httpclient (2.8.3)
     i18n (1.6.0)
       concurrent-ruby (~> 1.0)
+    i18n_data (0.8.0)
     icalendar (2.4.1)
     ice_nine (0.11.2)
     influxdb (0.2.3)
@@ -954,6 +959,7 @@ GEM
       json (>= 1.8, < 3)
       simplecov-html (~> 0.10.0)
     simplecov-html (0.10.2)
+    sixarm_ruby_unaccent (1.2.0)
     slack-notifier (1.5.1)
     snowplow-tracker (0.6.1)
       contracts (~> 0.7, <= 0.11)
@@ -1018,6 +1024,7 @@ GEM
       unf_ext
     unf_ext (0.0.7.5)
     unicode-display_width (1.6.0)
+    unicode_utils (1.4.0)
     unicorn (5.4.1)
       kgio (~> 2.6)
       raindrops (~> 0.7)
@@ -1117,6 +1124,7 @@ DEPENDENCIES
   commonmarker (~> 0.17)
   concurrent-ruby (~> 1.1)
   connection_pool (~> 2.0)
+  countries (~> 3.0)
   creole (~> 0.5.0)
   danger (~> 6.0)
   database_cleaner (~> 1.7.0)
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 33c909895487dca746c5bb605d829a8d4b6b8a76..5346bf45473163b0b2a0869a93926e6919bcbdec 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -613,3 +613,10 @@
     :why: https://bitbucket.org/atlassian/atlassian-jwt-ruby/src/master/LICENSE.txt
     :versions: []
     :when: 2019-08-30 05:45:35.317663000 Z
+- - :license
+  - unicode_utils
+  - MIT
+  - :who: Aishwarya Subramanain
+    :why: https://github.com/hexorx/countries/blob/master/LICENSE
+    :versions: []
+    :when: 2019-09-11 13:08:28.431132000 Z
diff --git a/config/initializers/countries.rb b/config/initializers/countries.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d65ae19852f0e2fca242dbce069d8f6a4883061c
--- /dev/null
+++ b/config/initializers/countries.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+ISO3166.configure do |config|
+  config.locales = [:en]
+end
+
+# GitLab permits users to sign up in Ukraine except the Crimean Region: https://about.gitlab.com/handbook/people-operations/code-of-conduct/#trade-compliance-exportimport-control
+# This overrides the display name for Ukraine to Ukraine (except Crimean Region)
+# To be removed after https://gitlab.com/gitlab-org/gitlab-ee/issues/14784 is implemented
+# Data fetched is based on https://github.com/hexorx/countries/blob/master/lib/countries/data/countries/UA.yaml
+ISO3166::Data.register(
+  continent: "Europe",
+  address_format: "|-
+  {{recipient}}
+  {{street}}
+  {{city}} {{region_short}}
+  {{postalcode}}
+  {{country}}",
+  alpha2: "UA",
+  alpha3: "UKR",
+  country_code: '380',
+  international_prefix: '810',
+  ioc: "UKR",
+  gec: "UP",
+  name: "Ukraine (except Crimean Region)",
+  national_destination_code_lengths: [2],
+  national_number_lengths: [8, 9],
+  national_prefix: '8',
+  number: '804',
+  region: "Europe",
+  subregion: "Eastern Europe",
+  world_region: "EMEA",
+  un_locode: "UA",
+  nationality: "Ukrainian",
+  vat_rates: {
+    standard: 20
+  },
+  reduced: [7],
+  super_reduced: {
+    parking: { postal_code: true }
+  },
+  unofficial_names: %w(Ukraine Ucrania ウクライナ Oekraïne Украина Україна Украіна),
+  languages_official: ["uk"],
+  languages_spoken: ["uk"],
+  geo: {
+    latitude: 48.379433,
+    latitude_dec: '48.92656326293945',
+    longitude: 31.16558,
+    longitude_dec: '31.47578239440918',
+    max_latitude: 52.37958099999999,
+    max_longitude: 40.2285809,
+    min_latitude: 44.2924,
+    min_longitude: 22.137159,
+    bounds: {
+      northeast: { lat: 52.37958099999999, lng: 40.2285809 },
+      southwest: { lat: 44.2924, lng: 22.137159 }
+    }
+  },
+  currency_code: "UAH",
+  start_of_week: "monday"
+)
diff --git a/config/routes.rb b/config/routes.rb
index 8ba3a7f3130a736b4ea493e74fd98e5d030ccdc5..9dbcd7fffa2c82255683bfc1f6398cac684f69a0 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -113,6 +113,7 @@
       draw :username
       draw :trial
       draw :trial_registration
+      draw :country
     end
 
     Gitlab.ee do
diff --git a/ee/app/controllers/countries_controller.rb b/ee/app/controllers/countries_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f703258e3c28227ff3fbe3d0da33b63061b99ff7
--- /dev/null
+++ b/ee/app/controllers/countries_controller.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class CountriesController < ActionController::Metal
+  include AbstractController::Rendering
+  include ActionController::Renderers::All
+
+  def index
+    countries = World.countries_for_select
+
+    render json: countries, status: (countries ? :ok : :not_found)
+  end
+end
diff --git a/ee/config/routes/country.rb b/ee/config/routes/country.rb
new file mode 100644
index 0000000000000000000000000000000000000000..419e37485bc360e71f2f4f0eade8c881278ee88b
--- /dev/null
+++ b/ee/config/routes/country.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+resources :countries, only: [:index]
diff --git a/ee/lib/world.rb b/ee/lib/world.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d99f8573f33ca92fe762c390feb337fecfbb0fe4
--- /dev/null
+++ b/ee/lib/world.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module World
+  include ::Gitlab::Utils::StrongMemoize
+  extend self
+
+  DENYLIST = ['Iran (Islamic Republic of)', 'Sudan', 'Syrian Arab Republic', 'Korea', 'Democratic People\'s Republic of', 'Cuba'].freeze
+
+  def countries_for_select
+    strong_memoize(:countries_for_select) { all_countries.sort_by(&:name).map { |c| [c.name, c.alpha2] } }
+  end
+
+  def all_countries
+    strong_memoize(:all_countries) { ISO3166::Country.all.reject {|item| DENYLIST.include?(item.name) } }
+  end
+end
diff --git a/ee/spec/controllers/countries_controller_spec.rb b/ee/spec/controllers/countries_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..315fbefa8d7065bf0e398a2d7838d1adcbae9d0b
--- /dev/null
+++ b/ee/spec/controllers/countries_controller_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe CountriesController do
+  describe 'GET #index' do
+    it 'returns list of countries as json' do
+      get :index
+
+      expected_json = World.countries_for_select.to_json
+
+      expect(response.status).to eq(200)
+      expect(response.body).to eq(expected_json)
+    end
+
+    it 'does not include list of denied countries' do
+      get :index
+
+      # response is returned as [["Afghanistan", "AF"], ["Albania", "AL"], ..]
+      resultant_countries = JSON.parse(response.body).map {|row| row[0]}
+
+      expect(resultant_countries).not_to include(World::DENYLIST)
+    end
+  end
+end
diff --git a/ee/spec/lib/world_spec.rb b/ee/spec/lib/world_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f4ec8977ad0a448e6d3427bd1b2a58336988176f
--- /dev/null
+++ b/ee/spec/lib/world_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe World do
+  describe '.all_countries' do
+    it 'does not return countries that are in the denied list' do
+      result = described_class.all_countries
+
+      expect(result.map(&:name)).not_to include(World::DENYLIST)
+    end
+  end
+
+  describe '.countries_for_select' do
+    it 'returns list of country name and iso_code in alphabetical format' do
+      result = described_class.countries_for_select
+
+      expect(result.first).to eq(%w[Afghanistan AF])
+    end
+  end
+end