Realm — mobilna, zorientowana obiektowo baza danych NoSQL, opracowana jako alternatywa dla SQLite i Core Data dla iOS i Android. Dane są przechowywane we własnym formacie z bezpośrednim dostępem do obiektów w pamięci, co zapewnia wysoką szybkość odczytu i zapisu. Dzięki reaktywnym powiadomieniom, automatycznej synchronizacji przez Realm Sync i wieloplatformowemu modelowi danych, Realm jest używany na ponad 1 miliardzie urządzeń (dane MongoDB, 2025).
Najważniejsze
Realm — to zorientowana obiektowo baza danych stworzona specjalnie dla aplikacji mobilnych. W przeciwieństwie do SQLite, Realm nie używa SQL ani modelu relacyjnego — dane są przechowywane jako żywe obiekty (Live Objects), do których dostęp odbywa się bezpośrednio, bez pośredniczącej warstwy ORM. Deweloper pracuje ze zwykłymi obiektami języka (Swift, Kotlin, Dart), które automatycznie zapisują się w bazie.
Realm pojawił się w 2014 roku jako startup Realm Inc., a w 2019 roku został przejęty przez MongoDB Inc. Od tego czasu Realm rozwija się jako MongoDB Realm — część jednolitej platformy Atlas Device Sync do mobilnej synchronizacji danych. Podstawowa lokalna baza Realm pozostaje bezpłatna i otwarta (licencja Apache 2.0), a Realm Sync (synchronizacja w chmurze) jest dostępny w subskrypcji.
Według MongoDB Developer Report (2025), Realm jest używany w 15% aplikacji mobilnych jako główne lokalne przechowywanie. Główne scenariusze to aplikacje z trybem offline, złożonymi modelami obiektowymi i potrzebą synchronizacji między urządzeniami, gdzie Realm przewyższa SQLite szybkością tworzenia i wygodą pracy z obiektami.
Live Objects — każdy obiekt Realm jest powiązany z dyskiem poprzez mapowanie pamięci (memory-mapped file). Zmiana obiektu w dowolnym wątku natychmiast odbija się we wszystkich innych wątkach bez ręcznego powiadamiania. Interfejs UI automatycznie przerysowuje się przy zmianie danych przez powiadomienia Realm. Zero-copy — Realm nie kopiuje danych z bazy do obiektów, obiekty to dane w pamięci.
Jądro Realm jest napisane w C++ i używa B+ Tree do indeksowania danych. W przeciwieństwie do SQLite, gdzie każdy wiersz to rekord w tabeli relacyjnej, Realm przechowuje obiekty jako węzły w strukturze grafowej z bezpośrednimi referencjami między nimi (forward pointers). Relacje między obiektami to nie klucze obce, ale bezpośrednie wskaźniki, co eliminuje potrzebę operacji JOIN.
Pliki Realm (rozszerzenie .realm) są memory-mapped — system operacyjny sam zarządza ładowaniem stron pliku do pamięci podczas dostępu. Pozwala to Realm pracować z bazami przekraczającymi dostępną pamięć RAM i zapewnia opóźnienie odczytu na poziomie natywnych struktur danych języka (Swift Array lub Kotlin List) dla danych mieszczących się w RAM.
Pliki memory-mapped — kluczowa technologia Realm. Zamiast kopiować dane z pliku bazy do obiektów języka (jak robi SQLite przez sqlite3_step + sqlite3_column_*), Realm odwzorowuje plik bazy bezpośrednio w przestrzeń adresową procesu. Obiekty języka to po prostu wskaźniki do danych w odwzorowanej pamięci. Zmiana obiektu modyfikuje bazę na dysku bez osobnego wywołania save.
| Cecha | Realm (zero-copy) | SQLite (kopiowanie) |
|---|---|---|
| Odczyt | Bezpośredni dostęp do pamięci (nanosekundy) | Kopiowanie do obiektu (mikrosekundy) |
| Zapis | Natychmiastowy zapis do memory-mapped file | save() z transakcją SQL INSERT/UPDATE |
| Relacje | Bezpośrednie wskaźniki (forward pointers) | Foreign key + JOIN |
| Zużycie pamięci | Plik + cache stron systemu | Obiekty + cache stron SQLite |
| Żywe obiekty | Tak (automatyczna aktualizacja) | Nie (wymagany nowy fetch) |
Zużycie pamięci Realm jest wyższe przy aktywnym odczycie (cały plik lub jego duża część jest odwzorowana w pamięci), ale niższe przy operacjach zapisu, ponieważ nie wymaga alokacji pamięci dla kopii obiektów. Dla baz o rozmiarze do 1 GB na urządzeniach mobilnych podejście memory-mapped daje lepszą ogólną wydajność niż SQLite z jego pośrednim kopiowaniem.
SQLite — relacyjny system zarządzania bazami danych z SQL i transakcjami ACID. Realm — obiektowa baza NoSQL z dostępem memory-mapped. Core Data — warstwa ORM Apple na SQLite. Każde z trzech podejść ma swój obszar zastosowania i mocne strony. Realm wygrywa w szybkości bezpośredniego dostępu do obiektów i reaktywności, SQLite — w uniwersalności i dojrzałości, Core Data — w integracji z ekosystemem Apple.
Wydajność Realm w operacjach odczytu jest o 10-50% wyższa niż SQLite dzięki dostępowi zero-copy. W operacjach zapisu Realm jest również szybszy dzięki brakowi analizy składniowej SQL i bezpośredniej modyfikacji stron memory-mapped. Jednak Realm może zużywać więcej pamięci RAM przy pracy z dużymi bazami (>500 MB), ponieważ plik jest w pełni odwzorowywany w przestrzeń adresową.
| Kryterium | Realm | SQLite | Core Data |
|---|---|---|---|
| Typ | NoSQL obiektowa baza | Relacyjna SZBD (SQL) | ORM na SQLite |
| Prędkość odczytu | Wysoka (zero-copy) | Średnia | Średnia (narzut ORM) |
| Reaktywność | Live Objects (wbudowana) | Wymaga otoczki (Room/GRDB) | NSFetchedResultsController |
| Synchronizacja | Realm Sync (MongoDB Atlas) | Wymaga własnej implementacji | NSPersistentCloudKitContainer |
| Platformy | iOS, Android, Flutter, RN, Node.js | iOS, Android, Web, Desktop | Tylko iOS/macOS |
| Rozmiar biblioteki | ~4 MB | ~600 KB | Wbudowane w SDK |
Wybór między Realm a SQLite często sprowadza się do priorytetów: szybkość tworzenia i reaktywność (Realm) przeciwko kontroli i uniwersalności (SQLite). Realm jest szczególnie dobry dla MVP i prototypów, gdzie model danych zmienia się często i ważne jest szybkie otrzymywanie żywych aktualizacji UI. SQLite/Room jest preferowany dla dojrzałych produktów z dużymi wolumenami danych i złożonymi zapytaniami analitycznymi.
Realm Kotlin SDK — oficjalna biblioteka dla Androida, napisana w Kotlin (nie otoczka nad Java SDK). Model danych jest definiowany przez klasy dziedziczące po RealmObject, z adnotacją @PrimaryKey dla unikalnego identyfikatora. Realm Kotlin wspiera Kotlin Coroutines, Flow i KSP (Kotlin Symbol Processing) do generowania kodu w czasie kompilacji.
RealmQuery zapewnia type-safe API do filtrowania bez SQL. Zapytania buduje się łańcuchem metod: query → filter → sort → find. Wynik może być zwrócony jako lista (z załadowaniem do pamięci) lub jako Flow (reaktywny strumień, aktualizujący się przy zmianie danych). Realm Kotlin wspiera również zagnieżdżone obiekty i listy (RealmList).
Model danych Realm jest definiowany jako data class implementująca interfejs RealmObject. Pole _id jest oznaczone @PrimaryKey dla unikalnej identyfikacji. Relacja jednen-do-wielu jest realizowana przez RealmList — listę innych RealmObject-ów. Wszystkie operacje zapisu (create, update, delete) są wykonywane wewnątrz bloku transakcji write.
class Project : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId().generate()
var name: String = ""
var tasks: RealmList<Task> = realmListOf()
}
class Task : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId().generate()
var title: String = ""
var isComplete: Boolean = false
}
val config = Realm.Configuration.Builder(
schema = setOf(Project::class, Task::class)
).build()
val realm = Realm.open(config)
realm.write { transactionRealm ->
val project = copyToRealm(Project().apply {
name = "Mobile App"
})
project.tasks.add(copyToRealm(Task().apply {
title = "Design UI"
}))
}
val projects: Flow<RealmResults<Project>> =
realm.query<Project>()
.sort(Project::name, Sort.ASCENDING)
.asFlow()
Zapytanie zwracające Flow automatycznie emituje nowe wyniki przy każdej zmianie danych w Realm: dodaniu, aktualizacji lub usunięciu Project lub Task. Podejście Flow idealnie współgra z Compose: collectAsState() w ViewModel automatycznie przebudowuje UI przy zmianie danych bez ręcznego aktualizowania adapterów list lub używania LiveData.
Realm Swift SDK zapewnia natywne Swift API z obsługą async/await, Combine Publishers i Swift Concurrency. Modele danych są definiowane jako klasy dziedziczące po Object, z użyciem @Persisted dla właściwości. Realm Swift automatycznie aktualizuje obiekty przy zmianach, a powiadomienia (NotificationToken) pozwalają subskrybować zmiany poszczególnych obiektów lub kolekcji.
@ObservedRealmObject i @ObservedResults — Property Wrappers dla SwiftUI, które automatycznie przerysowują View przy zmianie danych Realm. @ObservedResults działa z wynikami zapytania, @ObservedRealmObject — z konkretnym obiektem. Obie właściwości anulują subskrypcję przy deinicjalizacji View.
Integracja Realm ze SwiftUI — jedna z mocnych stron SDK. Property Wrapper @ObservedResults łączy zapytanie Realm z wyświetlaniem w SwiftUI. Przy zmianie dowolnego zadania SwiftUI automatycznie przebudowuje listę. realm.writeAsync wykonuje transakcje w wątku tła bez blokowania UI.
import RealmSwift
class TaskItem: Object, Identifiable {
@Persisted(primaryKey: true) var _id: ObjectId
@Persisted var title: String = ""
@Persisted var isDone: Bool = false
@Persisted var priority: Int = 0
}
struct TaskListView: View {
@ObservedResults(TaskItem.self,
sortDescriptor: SortDescriptor(["priority"]))
var tasks
var body: some View {
List {
ForEach(tasks) { task in
TaskRow(task: task)
}
}
Button("Dodaj zadanie") {
let realm = try! Realm()
try! realm.write {
realm.add(TaskItem(value: ["title": "New task"]))
}
}
}
}
@ObservedResults automatycznie zarządza cyklem życia zapytania Realm: przy tworzeniu View tworzona jest subskrypcja zmian, przy zniszczeniu — anulowana. Property Wrapper przyjmuje opcjonalny predykat (NSPredicate) i sortowanie. Eliminuje to konieczność ręcznego pisania zapytań fetch, tworzenia ViewModel i subskrybowania powiadomień Realm.
Aplikacje offline — Realm idealnie nadaje się do scenariuszy, gdzie dane muszą być dostępne bez internetu. Wbudowana synchronizacja (Realm Sync z MongoDB Atlas) automatycznie rozwiązuje konflikty przy połączeniu z siecią. Aplikacja nadal pracuje z lokalnymi danymi, a synchronizacja w tle aktualizuje je po pojawieniu się połączenia.
Interfejsy reaktywne — Live Objects i powiadomienia Flow/Combine czynią Realm wygodnym wyborem dla aplikacji z często aktualizowanymi danymi: czaty, listy zadań, dokumenty współdzielone. UI automatycznie aktualizuje się przy dodawaniu, zmianie lub usuwaniu danych bez ręcznego wywoływania reloadData lub invalidate.
Projekty wieloplatformowe — Realm wspiera Kotlin Multiplatform (KMP), Flutter, React Native i Xamarin. Model danych definiuje się raz i używa na wszystkich platformach. Zmniejsza to powielanie kodu i gwarantuje spójność schematu danych między aplikacjami iOS i Android ze wspólną logiką biznesową.
Realm Sync — usługa w chmurze wbudowana w MongoDB Atlas. Aplikacja automatycznie synchronizuje dane między urządzeniami użytkownika a serwerem. Konflikty są rozwiązywane według strategii last write wins lub przez niestandardowe Conflict Resolution Functions na serwerze. Realm Sync wspiera częściową synchronizację (subset of data) w celu zmniejszenia ruchu.
class SyncRepository {
private val app = App(
AppConfiguration(
appId = "my-realm-app-id"
)
)
suspend fun syncData() {
val user = app.login(Credentials.anonymous())
val config = SyncConfiguration.Builder(
user, setOf(Project::class)
).build()
val syncedRealm = Realm.open(config)
// Automatyczna synchronizacja aktywna
}
}
SyncConfiguration konfiguruje połączenie z MongoDB Atlas i określa zestaw synchronizowanych modeli. Po uwierzytelnieniu użytkownika Realm automatycznie ładuje dane z chmury i łączy je z lokalnymi zmianami. Synchronizacja działa w wątku tła i nie wymaga ręcznego wywoływania — wystarczy utworzyć instancję Realm z SyncConfiguration.
Często zadawane pytania
Tak, lokalna Realm baza danych jest całkowicie darmowa (licencja Apache 2.0). Realm Sync (synchronizacja w chmurze) przez MongoDB Atlas to płatna usługa wchodząca w skład subskrypcji Atlas Device Sync. Darmowy poziom Atlas oferuje pierwsze 500 MB danych i 1 milion operacji miesięcznie.
Tak, migracja jest możliwa przez eksport danych z SQLite do JSON i import do Realm przy pierwszym uruchomieniu aplikacji. Dla dużych wolumenów użyj migracji strumieniowej: równolegle zapisuj dane do obu baz, aż użytkownicy przejdą na nową wersję aplikacji, następnie usuń plik SQLite.
Realm Sync domyślnie używa strategii last write wins — ostatni zapis nadpisuje poprzedni. Dla złożonych konfliktów skonfiguruj niestandardowe Conflict Resolution Functions na serwerze MongoDB Atlas, które łączą zmiany z różnych urządzeń według logiki biznesowej aplikacji (np. scalanie wartości zamiast zastępowania).
Realm nie obsługuje agregacji SQL (SUM, AVG, GROUP BY) na poziomie bazy. Do zapytań analitycznych zaleca się eksport danych z Realm do MongoDB Atlas przez Realm Sync i wykonywanie agregacji przez MongoDB Aggregation Pipeline. Do prostych obliczeń użyj realm.query<T>().count().
Realm nie szyfruje danych domyślnie. Do szyfrowania podaj 64-bajtowy klucz w konfiguracji: Realm.Configuration(encryptionKey: key). Szyfrowanie używa AES-256 + SHA-2 HMAC i zwiększa narzut operacji o 10-20%. Bez szyfrowania plik .realm może być odczytany przez dowolny proces z dostępem do systemu plików.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również