diff --git a/chat-client-java/src/main/java/cz/muni/chat/client/Main.java b/chat-client-java/src/main/java/cz/muni/chat/client/Main.java
index 52fc3ec..3f90ddf 100644
--- a/chat-client-java/src/main/java/cz/muni/chat/client/Main.java
+++ b/chat-client-java/src/main/java/cz/muni/chat/client/Main.java
@@ -57,8 +57,14 @@ public void run(String... args) throws Exception {
             chat.createMessage(new NewChatMessageRequest().text("Message num " + i), "robot", null);
         }
         //get paged messages
-        PageChatMessage paged = chat.paged(1, 3, null);
-        log.info("paged messages:");
+        int pageIndex = 2;
+        int pageSize = 3;
+        PageChatMessage paged = chat.paged(pageIndex, pageSize, null);
+        log.info("paged messages: page={}/{} offset={} items={}/{} total={}",
+                paged.getNumber() + 1, paged.getTotalPages(),
+                paged.getPageable().getOffset(),
+                paged.getNumberOfElements(), paged.getSize(),
+                paged.getTotalElements());
         for (ChatMessage chatMessage : paged.getContent()) {
             log.info("msg: {}", chatMessage);
         }
diff --git a/chat-server/src/main/java/cz/muni/chat/server/rest/ChatRestController.java b/chat-server/src/main/java/cz/muni/chat/server/rest/ChatRestController.java
index 5ef5b5f..59b4192 100644
--- a/chat-server/src/main/java/cz/muni/chat/server/rest/ChatRestController.java
+++ b/chat-server/src/main/java/cz/muni/chat/server/rest/ChatRestController.java
@@ -24,7 +24,6 @@
 import org.springdoc.core.annotations.ParameterObject;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageImpl;
 import org.springframework.data.domain.Pageable;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
@@ -174,14 +173,7 @@ public ChatMessage createMessage(@Valid @RequestBody NewChatMessageRequest r,
     @GetMapping(path = "/paged", produces = MediaType.APPLICATION_JSON_VALUE)
     @CrossOrigin(origins = "*")
     public Page<ChatMessage> paged(@ParameterObject Pageable pageable) {
-        log.debug("/paged: pageable = {} offset = {}", pageable, pageable.getOffset());
-        List<StoredMessage> msgs = chatService.getAllChatMessages();
-        long total = msgs.size();
-        List<ChatMessage> chatMessages = msgs.stream()
-                .skip(pageable.getOffset())
-                .limit(pageable.getPageSize())
-                .map(ChatMessage::fromStoredMessage).toList();
-        return new PageImpl<>(chatMessages, pageable, total);
+        return chatService.getPageOfMessages(pageable).map(ChatMessage::fromStoredMessage);
     }
 
 }
diff --git a/chat-server/src/main/java/cz/muni/chat/server/service/ChatService.java b/chat-server/src/main/java/cz/muni/chat/server/service/ChatService.java
index 853d748..c5a1aaf 100644
--- a/chat-server/src/main/java/cz/muni/chat/server/service/ChatService.java
+++ b/chat-server/src/main/java/cz/muni/chat/server/service/ChatService.java
@@ -1,5 +1,8 @@
 package cz.muni.chat.server.service;
 
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
 import java.util.List;
 
 public interface ChatService {
@@ -9,4 +12,6 @@ public interface ChatService {
     StoredMessage createNewChatMessage(String text, String author, String textColor, String backgroundColor);
 
     StoredMessage getMessage(String id);
+
+    Page<StoredMessage> getPageOfMessages(Pageable pageable);
 }
diff --git a/chat-server/src/main/java/cz/muni/chat/server/service/ChatServiceImpl.java b/chat-server/src/main/java/cz/muni/chat/server/service/ChatServiceImpl.java
index 60e908c..18912d2 100644
--- a/chat-server/src/main/java/cz/muni/chat/server/service/ChatServiceImpl.java
+++ b/chat-server/src/main/java/cz/muni/chat/server/service/ChatServiceImpl.java
@@ -3,8 +3,11 @@
 import jakarta.annotation.PostConstruct;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
 import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
+import org.springframework.util.comparator.Comparators;
 
 import java.time.ZonedDateTime;
 import java.util.List;
@@ -42,4 +45,24 @@ public StoredMessage createNewChatMessage(String text, String author, String tex
     public StoredMessage getMessage(String id) {
         return messages.stream().filter(x -> x.id().equals(id)).findFirst().orElse(null);
     }
+
+    @Override
+    public Page<StoredMessage> getPageOfMessages(Pageable pageable) {
+        // In practice Pageable object is propagated into Spring Data repositories and transformed
+        // into LIMIT, OFFSET, and ORDER BY keywords in SQL queries, so the pagination is
+        // performed efficiently by the database engine when reading data from disk,
+        // which is the most time-consuming part of getting data.
+        //
+        // In this simple example, there is no persistence layer, so the following code gets all messages
+        // and then filters them in memory. That would be highly inefficient when using a real database.
+        // DO NOT perform pagination at the service level, do it at the persistence level!
+        List<StoredMessage> msgs = messages.stream()
+                .skip(pageable.getOffset())
+                .limit(pageable.getPageSize())
+                .toList();
+        Page<StoredMessage> page = new PageImpl<>(msgs, pageable, messages.size());
+        log.debug("pageable = {}", pageable);
+        log.debug("page: {}", page);
+        return page;
+    }
 }