diff --git a/app/graphql/resolvers/timelog_resolver.rb b/app/graphql/resolvers/timelog_resolver.rb
index 52c4508003a0c289ee801abc157c83bea209081f..dc42a5f38c95fcbffca42409d88ad73d99161fbb 100644
--- a/app/graphql/resolvers/timelog_resolver.rb
+++ b/app/graphql/resolvers/timelog_resolver.rb
@@ -34,19 +34,23 @@ class TimelogResolver < BaseResolver
              required: false,
              description: 'List timelogs for a user.'
 
+    argument :sort, Types::TimeTracking::TimelogSortEnum,
+             description: 'List timelogs in a particular order.',
+             required: false,
+             default_value: { field: 'spent_at', direction: :asc }
+
     def resolve_with_lookahead(**args)
       validate_args!(object, args)
 
-      timelogs = object&.timelogs || Timelog.limit(GitlabSchema.default_max_page_size)
+      timelogs = object&.timelogs || Timelog.all
 
-      if args.any?
-        args = parse_datetime_args(args)
+      args = parse_datetime_args(args)
 
-        timelogs = apply_user_filter(timelogs, args)
-        timelogs = apply_project_filter(timelogs, args)
-        timelogs = apply_time_filter(timelogs, args)
-        timelogs = apply_group_filter(timelogs, args)
-      end
+      timelogs = apply_user_filter(timelogs, args)
+      timelogs = apply_project_filter(timelogs, args)
+      timelogs = apply_time_filter(timelogs, args)
+      timelogs = apply_group_filter(timelogs, args)
+      timelogs = apply_sorting(timelogs, args)
 
       apply_lookahead(timelogs)
     end
@@ -60,7 +64,12 @@ def preloads
     end
 
     def validate_args!(object, args)
-      if args.empty? && object.nil?
+      # sort is always provided because of its default value so we
+      # should check the remaining args to make sure at least one filter
+      # argument was provided
+      cleaned_args = args.except(:sort)
+
+      if cleaned_args.empty? && object.nil?
         raise_argument_error('Provide at least one argument')
       elsif args[:start_time] && args[:start_date]
         raise_argument_error('Provide either a start date or time, but not both')
@@ -132,6 +141,15 @@ def apply_time_filter(timelogs, args)
       timelogs
     end
 
+    def apply_sorting(timelogs, args)
+      return timelogs unless args[:sort]
+
+      field = args[:sort][:field]
+      direction = args[:sort][:direction]
+
+      timelogs.sort_by_field(field, direction)
+    end
+
     def raise_argument_error(message)
       raise Gitlab::Graphql::Errors::ArgumentError, message
     end
diff --git a/app/graphql/types/time_tracking/timelog_sort_enum.rb b/app/graphql/types/time_tracking/timelog_sort_enum.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ad21c084d78af285a0a8af40a74b4d808719ef78
--- /dev/null
+++ b/app/graphql/types/time_tracking/timelog_sort_enum.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Types
+  module TimeTracking
+    class TimelogSortEnum < SortEnum
+      graphql_name 'TimelogSort'
+      description 'Values for sorting timelogs'
+
+      sortable_fields = ['Spent at', 'Time spent']
+
+      sortable_fields.each do |field|
+        value "#{field.upcase.tr(' ', '_')}_ASC",
+          value: { field: field.downcase.tr(' ', '_'), direction: :asc },
+          description: "#{field} by ascending order."
+        value "#{field.upcase.tr(' ', '_')}_DESC",
+          value: { field: field.downcase.tr(' ', '_'), direction: :desc },
+          description: "#{field} by descending order."
+      end
+    end
+  end
+end
diff --git a/app/models/timelog.rb b/app/models/timelog.rb
index 7c394736560c7566efc2a508daf58b07a4274fb2..07c61f64f29d0443a17d756c13a3dc117b5ceb43 100644
--- a/app/models/timelog.rb
+++ b/app/models/timelog.rb
@@ -35,10 +35,21 @@ class Timelog < ApplicationRecord
     where('spent_at <= ?', end_time)
   end
 
+  scope :order_scope_asc, ->(field) { order(arel_table[field].asc.nulls_last) }
+  scope :order_scope_desc, ->(field) { order(arel_table[field].desc.nulls_last) }
+
   def issuable
     issue || merge_request
   end
 
+  def self.sort_by_field(field, direction)
+    if direction == :asc
+      order_scope_asc(field)
+    else
+      order_scope_desc(field)
+    end
+  end
+
   private
 
   def issuable_id_is_present
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 5a60ed3aaa7356f1c7e6744f2929a9430f442c0e..f71aced27ef065f376ae36a98aca5b6ddc51e304 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -505,6 +505,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="querytimelogsendtime"></a>`endTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or before endTime. |
 | <a id="querytimelogsgroupid"></a>`groupId` | [`GroupID`](#groupid) | List timelogs for a group. |
 | <a id="querytimelogsprojectid"></a>`projectId` | [`ProjectID`](#projectid) | List timelogs for a project. |
+| <a id="querytimelogssort"></a>`sort` | [`TimelogSort`](#timelogsort) | List timelogs in a particular order. |
 | <a id="querytimelogsstartdate"></a>`startDate` | [`Time`](#time) | List timelogs within a date range where the logged date is equal to or after startDate. |
 | <a id="querytimelogsstarttime"></a>`startTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or after startTime. |
 | <a id="querytimelogsusername"></a>`username` | [`String`](#string) | List timelogs for a user. |
@@ -14171,6 +14172,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="grouptimelogsendtime"></a>`endTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or before endTime. |
 | <a id="grouptimelogsgroupid"></a>`groupId` | [`GroupID`](#groupid) | List timelogs for a group. |
 | <a id="grouptimelogsprojectid"></a>`projectId` | [`ProjectID`](#projectid) | List timelogs for a project. |
+| <a id="grouptimelogssort"></a>`sort` | [`TimelogSort`](#timelogsort) | List timelogs in a particular order. |
 | <a id="grouptimelogsstartdate"></a>`startDate` | [`Time`](#time) | List timelogs within a date range where the logged date is equal to or after startDate. |
 | <a id="grouptimelogsstarttime"></a>`startTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or after startTime. |
 | <a id="grouptimelogsusername"></a>`username` | [`String`](#string) | List timelogs for a user. |
@@ -15344,6 +15346,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="mergerequestassigneetimelogsendtime"></a>`endTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or before endTime. |
 | <a id="mergerequestassigneetimelogsgroupid"></a>`groupId` | [`GroupID`](#groupid) | List timelogs for a group. |
 | <a id="mergerequestassigneetimelogsprojectid"></a>`projectId` | [`ProjectID`](#projectid) | List timelogs for a project. |
+| <a id="mergerequestassigneetimelogssort"></a>`sort` | [`TimelogSort`](#timelogsort) | List timelogs in a particular order. |
 | <a id="mergerequestassigneetimelogsstartdate"></a>`startDate` | [`Time`](#time) | List timelogs within a date range where the logged date is equal to or after startDate. |
 | <a id="mergerequestassigneetimelogsstarttime"></a>`startTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or after startTime. |
 | <a id="mergerequestassigneetimelogsusername"></a>`username` | [`String`](#string) | List timelogs for a user. |
@@ -15574,6 +15577,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="mergerequestauthortimelogsendtime"></a>`endTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or before endTime. |
 | <a id="mergerequestauthortimelogsgroupid"></a>`groupId` | [`GroupID`](#groupid) | List timelogs for a group. |
 | <a id="mergerequestauthortimelogsprojectid"></a>`projectId` | [`ProjectID`](#projectid) | List timelogs for a project. |
+| <a id="mergerequestauthortimelogssort"></a>`sort` | [`TimelogSort`](#timelogsort) | List timelogs in a particular order. |
 | <a id="mergerequestauthortimelogsstartdate"></a>`startDate` | [`Time`](#time) | List timelogs within a date range where the logged date is equal to or after startDate. |
 | <a id="mergerequestauthortimelogsstarttime"></a>`startTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or after startTime. |
 | <a id="mergerequestauthortimelogsusername"></a>`username` | [`String`](#string) | List timelogs for a user. |
@@ -15823,6 +15827,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="mergerequestparticipanttimelogsendtime"></a>`endTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or before endTime. |
 | <a id="mergerequestparticipanttimelogsgroupid"></a>`groupId` | [`GroupID`](#groupid) | List timelogs for a group. |
 | <a id="mergerequestparticipanttimelogsprojectid"></a>`projectId` | [`ProjectID`](#projectid) | List timelogs for a project. |
+| <a id="mergerequestparticipanttimelogssort"></a>`sort` | [`TimelogSort`](#timelogsort) | List timelogs in a particular order. |
 | <a id="mergerequestparticipanttimelogsstartdate"></a>`startDate` | [`Time`](#time) | List timelogs within a date range where the logged date is equal to or after startDate. |
 | <a id="mergerequestparticipanttimelogsstarttime"></a>`startTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or after startTime. |
 | <a id="mergerequestparticipanttimelogsusername"></a>`username` | [`String`](#string) | List timelogs for a user. |
@@ -16071,6 +16076,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="mergerequestreviewertimelogsendtime"></a>`endTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or before endTime. |
 | <a id="mergerequestreviewertimelogsgroupid"></a>`groupId` | [`GroupID`](#groupid) | List timelogs for a group. |
 | <a id="mergerequestreviewertimelogsprojectid"></a>`projectId` | [`ProjectID`](#projectid) | List timelogs for a project. |
+| <a id="mergerequestreviewertimelogssort"></a>`sort` | [`TimelogSort`](#timelogsort) | List timelogs in a particular order. |
 | <a id="mergerequestreviewertimelogsstartdate"></a>`startDate` | [`Time`](#time) | List timelogs within a date range where the logged date is equal to or after startDate. |
 | <a id="mergerequestreviewertimelogsstarttime"></a>`startTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or after startTime. |
 | <a id="mergerequestreviewertimelogsusername"></a>`username` | [`String`](#string) | List timelogs for a user. |
@@ -18325,6 +18331,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="projecttimelogsendtime"></a>`endTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or before endTime. |
 | <a id="projecttimelogsgroupid"></a>`groupId` | [`GroupID`](#groupid) | List timelogs for a group. |
 | <a id="projecttimelogsprojectid"></a>`projectId` | [`ProjectID`](#projectid) | List timelogs for a project. |
+| <a id="projecttimelogssort"></a>`sort` | [`TimelogSort`](#timelogsort) | List timelogs in a particular order. |
 | <a id="projecttimelogsstartdate"></a>`startDate` | [`Time`](#time) | List timelogs within a date range where the logged date is equal to or after startDate. |
 | <a id="projecttimelogsstarttime"></a>`startTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or after startTime. |
 | <a id="projecttimelogsusername"></a>`username` | [`String`](#string) | List timelogs for a user. |
@@ -20178,6 +20185,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="usercoretimelogsendtime"></a>`endTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or before endTime. |
 | <a id="usercoretimelogsgroupid"></a>`groupId` | [`GroupID`](#groupid) | List timelogs for a group. |
 | <a id="usercoretimelogsprojectid"></a>`projectId` | [`ProjectID`](#projectid) | List timelogs for a project. |
+| <a id="usercoretimelogssort"></a>`sort` | [`TimelogSort`](#timelogsort) | List timelogs in a particular order. |
 | <a id="usercoretimelogsstartdate"></a>`startDate` | [`Time`](#time) | List timelogs within a date range where the logged date is equal to or after startDate. |
 | <a id="usercoretimelogsstarttime"></a>`startTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or after startTime. |
 | <a id="usercoretimelogsusername"></a>`username` | [`String`](#string) | List timelogs for a user. |
@@ -22850,6 +22858,25 @@ Category of error.
 | <a id="timeboxreporterrorreasonupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_ASC`. |
 | <a id="timeboxreporterrorreasonupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_DESC`. |
 
+### `TimelogSort`
+
+Values for sorting timelogs.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="timelogsortcreated_asc"></a>`CREATED_ASC` | Created at ascending order. |
+| <a id="timelogsortcreated_desc"></a>`CREATED_DESC` | Created at descending order. |
+| <a id="timelogsortspent_at_asc"></a>`SPENT_AT_ASC` | Spent at by ascending order. |
+| <a id="timelogsortspent_at_desc"></a>`SPENT_AT_DESC` | Spent at by descending order. |
+| <a id="timelogsorttime_spent_asc"></a>`TIME_SPENT_ASC` | Time spent by ascending order. |
+| <a id="timelogsorttime_spent_desc"></a>`TIME_SPENT_DESC` | Time spent by descending order. |
+| <a id="timelogsortupdated_asc"></a>`UPDATED_ASC` | Updated at ascending order. |
+| <a id="timelogsortupdated_desc"></a>`UPDATED_DESC` | Updated at descending order. |
+| <a id="timelogsortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_ASC`. |
+| <a id="timelogsortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_DESC`. |
+| <a id="timelogsortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_ASC`. |
+| <a id="timelogsortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_DESC`. |
+
 ### `TodoActionEnum`
 
 | Value | Description |
@@ -24464,6 +24491,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="usertimelogsendtime"></a>`endTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or before endTime. |
 | <a id="usertimelogsgroupid"></a>`groupId` | [`GroupID`](#groupid) | List timelogs for a group. |
 | <a id="usertimelogsprojectid"></a>`projectId` | [`ProjectID`](#projectid) | List timelogs for a project. |
+| <a id="usertimelogssort"></a>`sort` | [`TimelogSort`](#timelogsort) | List timelogs in a particular order. |
 | <a id="usertimelogsstartdate"></a>`startDate` | [`Time`](#time) | List timelogs within a date range where the logged date is equal to or after startDate. |
 | <a id="usertimelogsstarttime"></a>`startTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or after startTime. |
 | <a id="usertimelogsusername"></a>`username` | [`String`](#string) | List timelogs for a user. |
diff --git a/spec/graphql/resolvers/timelog_resolver_spec.rb b/spec/graphql/resolvers/timelog_resolver_spec.rb
index da2747fdf72509995d505157226ac5ab37a423b6..cd52308d8959f4e61582d30972b21c92db1b9f8d 100644
--- a/spec/graphql/resolvers/timelog_resolver_spec.rb
+++ b/spec/graphql/resolvers/timelog_resolver_spec.rb
@@ -2,7 +2,7 @@
 
 require 'spec_helper'
 
-RSpec.describe Resolvers::TimelogResolver do
+RSpec.describe Resolvers::TimelogResolver, feature_category: :team_planning do
   include GraphqlHelpers
 
   let_it_be(:current_user) { create(:user) }
@@ -262,18 +262,6 @@
     it_behaves_like 'with a user'
   end
 
-  context 'when > `default_max_page_size` records' do
-    let(:object) { nil }
-    let!(:timelog_list) { create_list(:timelog, 101, issue: issue) }
-    let(:args) { { project_id: global_id_of(project) } }
-    let(:extra_args) { {} }
-
-    it 'pagination returns `default_max_page_size` and sets `has_next_page` true' do
-      expect(timelogs.items.count).to be(100)
-      expect(timelogs.has_next_page).to be(true)
-    end
-  end
-
   context 'when no object or arguments provided' do
     let(:object) { nil }
     let(:args) { {} }
@@ -286,6 +274,21 @@
     end
   end
 
+  context 'when the sort argument is provided' do
+    let_it_be(:timelog_a) { create(:issue_timelog, time_spent: 7200, spent_at: 1.hour.ago, user: current_user) }
+    let_it_be(:timelog_b) { create(:issue_timelog, time_spent: 5400, spent_at: 2.hours.ago, user: current_user) }
+    let_it_be(:timelog_c) { create(:issue_timelog, time_spent: 1800, spent_at: 30.minutes.ago, user: current_user) }
+    let_it_be(:timelog_d) { create(:issue_timelog, time_spent: 3600, spent_at: 1.day.ago, user: current_user) }
+
+    let(:object) { current_user }
+    let(:args) { { sort: 'TIME_SPENT_ASC' } }
+    let(:extra_args) { {} }
+
+    it 'returns all the timelogs in the correct order' do
+      expect(timelogs.items).to eq([timelog_c, timelog_d, timelog_b, timelog_a])
+    end
+  end
+
   def resolve_timelogs(user: current_user, obj: object, **args)
     context = { current_user: user }
     resolve(described_class, obj: obj, args: args.merge(extra_args), ctx: context)
diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb
index 514d24a209e5f44144265a1ecf8d26492a82461f..b09b3b6e6c70f7dadd4526375b2c72cd637b874f 100644
--- a/spec/graphql/types/query_type_spec.rb
+++ b/spec/graphql/types/query_type_spec.rb
@@ -135,7 +135,7 @@
     subject { described_class.fields['timelogs'] }
 
     it 'returns timelogs' do
-      is_expected.to have_graphql_arguments(:startDate, :endDate, :startTime, :endTime, :username, :projectId, :groupId, :after, :before, :first, :last)
+      is_expected.to have_graphql_arguments(:startDate, :endDate, :startTime, :endTime, :username, :projectId, :groupId, :after, :before, :first, :last, :sort)
       is_expected.to have_graphql_type(Types::TimelogType.connection_type)
       is_expected.to have_graphql_resolver(Resolvers::TimelogResolver)
     end
diff --git a/spec/graphql/types/time_tracking/timelog_sort_enum_spec.rb b/spec/graphql/types/time_tracking/timelog_sort_enum_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ecc11256c858bfc838606c4bb7cecb74ea7570ef
--- /dev/null
+++ b/spec/graphql/types/time_tracking/timelog_sort_enum_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['TimelogSort'], feature_category: :team_planning do
+  specify { expect(described_class.graphql_name).to eq('TimelogSort') }
+
+  it_behaves_like 'common sort values'
+
+  it 'exposes all the contact sort values' do
+    expect(described_class.values.keys).to include(
+      *%w[
+        SPENT_AT_ASC
+        SPENT_AT_DESC
+        TIME_SPENT_ASC
+        TIME_SPENT_DESC
+      ]
+    )
+  end
+end
diff --git a/spec/models/timelog_spec.rb b/spec/models/timelog_spec.rb
index f96d02e6a82be2f48766ab70fbce26657c720021..515057a862b065ce7110b75915031a358af5a200 100644
--- a/spec/models/timelog_spec.rb
+++ b/spec/models/timelog_spec.rb
@@ -2,7 +2,7 @@
 
 require 'spec_helper'
 
-RSpec.describe Timelog do
+RSpec.describe Timelog, feature_category: :team_planning do
   subject { create(:timelog) }
 
   let_it_be(:issue) { create(:issue) }
@@ -149,4 +149,30 @@ def just_after(time)
       end
     end
   end
+
+  describe 'sorting' do
+    let_it_be(:user) { create(:user) }
+    let_it_be(:timelog_a) { create(:issue_timelog, time_spent: 7200, spent_at: 1.hour.ago, user: user) }
+    let_it_be(:timelog_b) { create(:issue_timelog, time_spent: 5400, spent_at: 2.hours.ago, user: user) }
+    let_it_be(:timelog_c) { create(:issue_timelog, time_spent: 1800, spent_at: 30.minutes.ago, user: user) }
+    let_it_be(:timelog_d) { create(:issue_timelog, time_spent: 3600, spent_at: 1.day.ago, user: user) }
+
+    describe '.sort_by_field' do
+      it 'sorts timelogs by time spent in ascending order' do
+        expect(user.timelogs.sort_by_field('time_spent', :asc)).to eq([timelog_c, timelog_d, timelog_b, timelog_a])
+      end
+
+      it 'sorts timelogs by time spent in descending order' do
+        expect(user.timelogs.sort_by_field('time_spent', :desc)).to eq([timelog_a, timelog_b, timelog_d, timelog_c])
+      end
+
+      it 'sorts timelogs by spent at in ascending order' do
+        expect(user.timelogs.sort_by_field('spent_at', :asc)).to eq([timelog_d, timelog_b, timelog_a, timelog_c])
+      end
+
+      it 'sorts timelogs by spent at in descending order' do
+        expect(user.timelogs.sort_by_field('spent_at', :desc)).to eq([timelog_c, timelog_a, timelog_b, timelog_d])
+      end
+    end
+  end
 end