REST API vs GraphQL
REST, con más de 20 años de historia, se enfrenta a GraphQL, nacido en Facebook. ¿Qué paradigma de diseño de API deberías elegir para el backend de tu aplicación móvil?
La completa plataforma de desarrollo de apps móviles de Google
Alternativa de código abierto a Firebase — basada en PostgreSQL, auto-hospedable
| Categoría | Firebase | Supabase |
|---|---|---|
| Rendimiento | 9/10 | 9/10 |
| Facilidad de aprendizaje | 8/10 | 7/10 |
| Ecosistema | 10/10 | 7/10 |
| Comunidad | 9/10 | 8/10 |
| Mercado laboral | 9/10 | 7/10 |
| A prueba de futuro | 7/10 | 9/10 |
// Firebase - Mensajes de chat en tiempo real
import FirebaseFirestore
import FirebaseAuth
import SwiftUI
@Observable
class ChatViewModel {
var messages: [Message] = []
private var listener: ListenerRegistration?
private let db = Firestore.firestore()
struct Message: Identifiable, Codable {
@DocumentID var id: String?
let senderId: String
let senderName: String
let text: String
let timestamp: Timestamp
}
func startListening(roomId: String) {
listener = db.collection("rooms")
.document(roomId)
.collection("messages")
.order(by: "timestamp", descending: false)
.limit(toLast: 50)
.addSnapshotListener { [weak self] snapshot, error in
guard let documents = snapshot?.documents else { return }
self?.messages = documents.compactMap {
try? $0.data(as: Message.self)
}
}
}
func sendMessage(text: String, roomId: String) async throws {
guard let user = Auth.auth().currentUser else { return }
let message = Message(
senderId: user.uid,
senderName: user.displayName ?? "Anónimo",
text: text,
timestamp: Timestamp()
)
try db.collection("rooms")
.document(roomId)
.collection("messages")
.addDocument(from: message)
}
func stopListening() { listener?.remove() }
}// Supabase - CRUD de publicaciones de usuario
import Supabase
import Foundation
struct Post: Codable, Identifiable {
let id: UUID
let userId: UUID
let title: String
let content: String
let createdAt: Date
enum CodingKeys: String, CodingKey {
case id, title, content
case userId = "user_id"
case createdAt = "created_at"
}
}
class PostRepository {
private let client = SupabaseClient(
supabaseURL: URL(string: ProcessInfo.processInfo.environment["SUPABASE_URL"]!)!,
supabaseKey: ProcessInfo.processInfo.environment["SUPABASE_ANON_KEY"]!
)
func fetchPosts() async throws -> [Post] {
try await client
.from("posts")
.select("*")
.order("created_at", ascending: false)
.limit(20)
.execute()
.value
}
func createPost(title: String, content: String) async throws -> Post {
let userId = try await client.auth.session.user.id
return try await client
.from("posts")
.insert(["user_id": userId.uuidString, "title": title, "content": content])
.select()
.single()
.execute()
.value
}
func subscribeToNewPosts(onNewPost: @escaping (Post) -> Void) -> RealtimeChannelV2 {
let channel = client.channel("public:posts")
channel.onPostgresChange(
InsertAction.self,
table: "posts"
) { change in
if let post = try? change.record.decode(as: Post.self) {
onNewPost(post)
}
}
Task { await channel.subscribe() }
return channel
}
}Firebase es potente para desarrollo rápido, un SDK de iOS excelente y funciones en tiempo real. Si necesitas datos relacionales, flexibilidad SQL, código abierto o te preocupa el vendor lock-in, elige Supabase. En 2025, Supabase está madurando rápidamente y se ha convertido en una alternativa seria — especialmente su integración con pgvector destaca para aplicaciones con funciones de IA.
Solicita una consultoría gratuitaEs posible, pero no es fácil. La estructura NoSQL de Firestore debe convertirse a un esquema de PostgreSQL, hay que migrar los usuarios de Auth y transferir los archivos de Storage. Requiere un proyecto de migración considerable.