Capítulo 3 de 10 · 100 proyectos para hacer con tu coding agent
APIs y back-end (21-30)
Diez proyectos de servidor con las partes difíciles incluidas: colas que sobreviven a caídas, autenticación hecha a mano, multi-tenant con aislamiento real y un gateway.
Un CRUD te lo genera cualquier agente en dos minutos, y está bien, pero ahí no se aprende nada. Lo interesante empieza después. Qué pasa cuando llegan dos peticiones a la vez, cuando el trabajador se cae a mitad de un trabajo o cuando alguien te manda un millón de peticiones por minuto.
Los prompts de este capítulo están escritos justo para forzar esas situaciones.
21. Acortador de URLs con estadísticas
El «hola mundo» del back-end, pero tomándoselo en serio. Códigos sin colisiones, redirecciones con la cabecera correcta y contadores que no pierdan clics cuando hay carga.
Construye un acortador de URLs con API y una página mínima.
- POST /links crea un código corto (base62, 7 caracteres, sin colisiones).
- GET /:code redirige con 301 o 302 según configuración, y explica en el
README por qué esa elección importa para las estadísticas.
- Contador de clics agregado por día, país y referente.
- Enlaces con caducidad y con contraseña opcional.
El registro de clics no debe ralentizar la redirección: hazlo asíncrono
y demuéstralo con una prueba de carga sencilla.
22. Cola de trabajos con reintentos
Todo servicio acaba necesitando una cola, y escribir la tuya te enseña qué significa de verdad «al menos una vez» y por qué tus trabajos tienen que ser idempotentes. Además la haremos sobre Postgres, que probablemente ya tienes.
Implementa una cola de trabajos persistente sobre PostgreSQL (nada de Redis).
- encolar(tipo, payload, ejecutar_en) y trabajadores que hacen polling con
SELECT ... FOR UPDATE SKIP LOCKED.
- Reintentos con retroceso exponencial y jitter, máximo configurable.
- Cola de mensajes fallidos y comando para reencolar desde ella.
- Trabajos programados (cron) y trabajos únicos por clave de idempotencia.
Escribe un test que mate al trabajador a mitad de un trabajo y compruebe
que ese trabajo se recupera y no se ejecuta dos veces con efectos visibles.
23. Autenticación completa hecha a mano
Sin Auth0 y sin Firebase. Contraseñas con Argon2, sesiones que rotan, verificación por correo y recuperación de cuenta. No es que después vayas a dejar de usar un proveedor, pero entenderás exactamente qué le estás delegando.
Escribe un sistema de autenticación completo, sin librerías de auth de terceros.
- Registro con verificación por correo (token de un solo uso, con caducidad).
- Contraseñas con Argon2id y parámetros justificados en un comentario.
- Sesiones con cookie httpOnly + SameSite, rotación en cada login y
revocación de todas las sesiones desde el perfil.
- Recuperación de contraseña sin filtrar si el correo existe.
- Límite de intentos por IP y por cuenta, con bloqueo temporal.
Añade una sección al README con las decisiones de seguridad y sus porqués.
24. API con GraphQL y carga por lotes
El problema N+1, aprendido a base de sufrirlo. Primero lo escribes mal, mides cuántas consultas salen, y después metes un dataloader y vuelves a medir.
Crea una API GraphQL sobre un modelo de datos con relaciones profundas
(autores -> libros -> reseñas -> usuarios).
Fase 1: implementación ingenua. Mide y enséñame cuántas consultas SQL
lanza una query anidada.
Fase 2: implementa el patrón dataloader (batching + caché por petición)
y vuelve a medir.
Fase 3: limita la profundidad y la complejidad de las consultas para que
nadie pueda tumbar el servidor con una query anidada.
Incluye un test que falle si vuelve a aparecer el N+1.
25. Servidor de webhooks con firma y reintentos
Emitir webhooks es fácil hasta que el receptor está caído, o tarda 30 segundos, o responde 200 y luego dice que no le llegó nada. Aquí construyes el lado que envía, con firmas HMAC y una política de reintentos seria.
Construye un servicio de entrega de webhooks.
- Suscripciones por evento y por endpoint, con secreto por suscripción.
- Firma HMAC-SHA256 con marca de tiempo en la cabecera, resistente a replay.
- Reintentos con retroceso exponencial durante 24 h; desactivación automática
del endpoint tras N fallos consecutivos, con aviso.
- Panel para ver los intentos, la respuesta recibida y reenviar a mano.
Incluye un receptor de ejemplo que verifique la firma correctamente,
y otro que la verifique mal, para enseñar el error típico.
26. Multi-tenancy con aislamiento real
Varias empresas en la misma base de datos sin que ninguna pueda ver los datos de las demás. De todo el capítulo, es el proyecto que más se parece a un trabajo real.
Diseña e implementa una API multi-tenant con aislamiento por fila.
- Usa Row Level Security de PostgreSQL, no filtros en el código.
- El tenant se resuelve desde el token y se fija por conexión con SET LOCAL.
- Un mismo usuario puede pertenecer a varios tenants y cambiar entre ellos.
- Migraciones y seeds que funcionen con RLS activo.
El test más importante: intentar leer datos de otro tenant por todas las vías
que se te ocurran (id directo, relación, subconsulta) y que todas fallen.
27. Servidor de subida de archivos con troceado
Subir un vídeo de 2 GB desde un móvil con mala cobertura. Necesitas troceado, poder reanudar donde se cortó y limpiar los restos de las subidas que nunca terminan.
Haz un servicio de subida de ficheros grandes con reanudación.
- Protocolo por trozos: iniciar subida, subir trozo N, completar.
- Reanudable: el cliente pregunta qué trozos faltan y sigue por ahí.
- Verificación de integridad por trozo y del fichero completo.
- Limpieza de subidas abandonadas pasadas 24 h.
- Almacenamiento detrás de una interfaz: disco local o S3, intercambiables.
Cliente de ejemplo en la terminal que muestre progreso y sobreviva a
un corte de red simulado.
28. Gateway de API con límite de tasa
Enrutado, autenticación, límites de tasa y reintentos en un único punto de entrada. Vas a implementar el token bucket y la ventana deslizante, y al compararlos entenderás por qué existen los dos.
Construye un gateway de API inverso, configurado por YAML.
- Enrutado por host y ruta hacia servicios internos.
- Límite de tasa: implementa token bucket y sliding window log, elige por ruta,
y explica las diferencias con un test que lo demuestre.
- Cortacircuitos por servicio: abre tras N fallos, semiabierto tras X segundos.
- Cabeceras de trazado propagadas (traceparent) y logs estructurados.
Todo el estado de límites en memoria primero; luego abstrae para poder
usar Redis y que funcione con varias instancias.
29. Motor de sincronización con resolución de conflictos
El corazón de cualquier aplicación que funcione sin conexión. Dos dispositivos editan lo mismo estando offline y luego tienen que ponerse de acuerdo sin perder datos. Es un problema mucho más profundo de lo que parece desde fuera.
Implementa un motor de sincronización cliente-servidor para datos offline.
- El cliente guarda cambios locales en una bitácora con reloj lógico.
- Sincronización por deltas desde el último cursor conocido.
- Resolución de conflictos: por campo, con "último en escribir gana" y marca
de tiempo híbrida; conflictos irresolubles quedan marcados para el usuario.
- Borrados como tumbas, con recolección de basura pasado un plazo.
Simula tres clientes editando el mismo registro sin conexión y enséñame
el estado final de todos ellos: debe converger.
30. Framework web mínimo desde el socket
Sin librerías HTTP de ningún tipo. Abres un socket, parseas la petición a mano y descubres por qué
existen Content-Length y Transfer-Encoding, y por qué los servidores web son tan quisquillosos
con las peticiones malformadas.
Escribe un framework web mínimo partiendo de sockets TCP crudos.
1. Parseo de HTTP/1.1 a mano: línea de petición, cabeceras, cuerpo con
Content-Length y con chunked.
2. Enrutador con parámetros de ruta y middlewares encadenables.
3. Keep-alive, timeouts y límite de tamaño de petición.
4. Pool de hilos o bucle de eventos (elige y justifica).
Prueba con curl, con peticiones malformadas y con una petición que se corta
a la mitad. Nada debe tumbar el servidor.