Talently
Talently
Desarrollador Back-End

Desarrollador Back-End

Construye los sistemas, APIs y lógica de negocio que hacen funcionar los productos digitales a escala.

Un Back-End Developer diseña e implementa la lógica del servidor, las APIs y la capa de datos que sustentan los productos digitales. Es responsable de garantizar que los sistemas sean seguros, escalables y mantenibles. Trabaja en estrecha colaboración con desarrolladores frontend, arquitectos, DBAs y equipos de infraestructura para definir contratos de API, modelar datos y resolver problemas de rendimiento bajo carga real. Su trabajo determina en gran medida la confiabilidad y capacidad de evolución del producto.

PythonREST APIs / GraphQLSQL / NoSQLDockerAutenticación y SeguridadJava

Recluta al mejor Desarrollador Back-End aquí

Empieza ahora

Responsabilidades Principales

  • Diseñar e implementar APIs REST o GraphQL con contratos claros, versionado y documentación (OpenAPI, GraphQL schema).
  • Modelar y optimizar esquemas de bases de datos relacionales y no relacionales según los patrones de acceso requeridos.
  • Implementar mecanismos de autenticación y autorización seguros (OAuth2, JWT, RBAC).
  • Diseñar flujos asíncronos con colas de mensajes (Kafka, RabbitMQ, SQS) para desacoplar servicios y manejar picos de carga.
  • Diagnosticar y resolver cuellos de botella de rendimiento en queries, caché y consumo de recursos.
  • Escribir tests automatizados (unit, integración, contrato) y mantener pipelines de CI/CD confiables.

Habilidades Clave

Technical Skills

  • Dominio de al menos un lenguaje backend: Node.js, Python, Java, Go o .NET con sus frameworks principales
  • Diseño de APIs REST y GraphQL: recursos, contratos, versionado, paginación y manejo de errores
  • Bases de datos relacionales (PostgreSQL, MySQL) y NoSQL (MongoDB, Redis, DynamoDB) con criterio para elegir entre ellas
  • Implementación de autenticación y autorización con OAuth2, JWT y modelos de permisos (RBAC, ABAC)
  • Sistemas de mensajería y colas asíncronas: Kafka, RabbitMQ, SQS o equivalentes
  • Contenerización con Docker y orquestación básica con Kubernetes o servicios cloud equivalentes
  • Testing: unit tests con mocking de dependencias, tests de integración con bases de datos reales, contract testing con Pact

Soft Skills

  • Capacidad de diseñar soluciones técnicas y comunicarlas con diagramas o documentación clara a distintas audiencias
  • Criterio para evaluar tradeoffs entre consistencia, disponibilidad y rendimiento en decisiones de arquitectura
  • Colaboración activa con frontend en la definición de contratos de API antes de iniciar implementación
  • Pensamiento sistemático para trazar el impacto de un cambio de schema o API en sistemas dependientes
  • Proactividad para detectar deuda técnica y proponer refactorizaciones con justificación de negocio
  • Comunicación asertiva al discutir requerimientos técnicamente inviables con stakeholders no técnicos

Casos de uso reales

Contexto

Las APIs backend son el contrato entre el servidor y sus consumidores (web, móvil, terceros). Un diseño pobre genera acoplamiento, breaking changes y deuda técnica acumulada.

Ejemplos reales

  • APIs RESTful con versionado en URL o headers para evolución sin ruptura
  • APIs GraphQL con schema federation para múltiples equipos
  • APIs con rate limiting, throttling y quotas por cliente
  • Documentación automática con OpenAPI/Swagger integrada al pipeline

Contexto

No toda operación puede o debe ejecutarse de forma síncrona. Las colas y sistemas de eventos permiten desacoplar servicios, absorber picos de carga y garantizar procesamiento eventual.

Ejemplos reales

  • Procesamiento de pagos con garantías de exactamente una vez (idempotencia)
  • Envío de emails y notificaciones push desacoplado del flujo principal
  • Pipelines de ingesta de datos con Kafka para múltiples consumidores
  • Workflows de background jobs con reintentos y dead letter queues

Contexto

La seguridad en el backend es no negociable. Un modelo de autenticación mal diseñado es la fuente de la mayoría de las vulnerabilidades críticas en aplicaciones web.

Ejemplos reales

  • Flujo OAuth2 con Authorization Code PKCE para aplicaciones SPA y móvil
  • Sistema de permisos granular basado en roles (RBAC) o atributos (ABAC)
  • Autenticación multi-tenant con aislamiento de datos por organización
  • Rotación automática de tokens y manejo seguro de sesiones

Contexto

Un sistema que funciona bien en desarrollo puede fallar bajo carga real. El backend debe identificar y resolver cuellos de botella antes de que impacten a usuarios.

Ejemplos reales

  • Optimización de queries SQL con explain plans e índices compuestos
  • Implementación de caching con Redis en capas (query cache, session cache)
  • Paginación eficiente con cursor-based pagination para conjuntos grandes
  • Identificación de N+1 queries con APM tools (Datadog, New Relic)

Contexto

Los esquemas de base de datos evolucionan con el producto. Gestionar migraciones sin downtime es una habilidad crítica para sistemas en producción con usuarios activos.

Ejemplos reales

  • Migraciones zero-downtime con estrategia expand-contract
  • Versionado de migraciones con Flyway, Liquibase o Alembic
  • Backfills de datos seguros en tablas con millones de registros
  • Estrategias de rollback ante migraciones fallidas en producción

Preguntas básicas

Relacional cuando los datos tienen estructura definida, relaciones complejas o se requiere consistencia transaccional (ACID). NoSQL cuando los datos son semiestructurados, el esquema cambia frecuentemente, se necesita escala horizontal masiva o los patrones de acceso son simples y predecibles. La decisión también depende del equipo y el ecosistema existente.
Usar sustantivos para recursos (no verbos), jerarquías que reflejen relaciones reales, HTTP methods semánticamente correctos (GET idempotente, POST para crear, PUT/PATCH para actualizar), status codes apropiados y mensajes de error estructurados. Versionar desde el inicio si la API es pública o compartida con otros equipos.
Sesiones: estado centralizado en servidor, revocación inmediata posible, mejor para aplicaciones web tradicionales con un solo dominio. JWT: stateless, escala horizontalmente sin coordinación, adecuado para APIs consumidas por SPAs y móvil. JWT tiene el problema de revocación: si el token está comprometido antes de expirar, no hay forma nativa de invalidarlo sin mantener una blacklist.
Una operación es idempotente si ejecutarla múltiples veces produce el mismo resultado que ejecutarla una vez. GET, PUT y DELETE deben ser idempotentes. En operaciones críticas como pagos o envíos, diseñar endpoints POST idempotentes con claves de idempotencia previene procesamiento duplicado ante reintentos de red.
Definir un formato de error consistente con código, mensaje human-readable y opcionalmente un campo de detalles para el cliente. Separar errores de cliente (4xx) de errores del servidor (5xx). Nunca exponer stack traces en producción. Loggear con contexto suficiente (request ID, user ID, timestamp) para debugging sin exponer datos sensibles.
Idempotency keys en el cliente para operaciones críticas. Transacciones de base de datos con constraints de unicidad. Patrón outbox para garantizar que un evento se emite exactamente una vez junto a la escritura en BD. En sistemas de mensajería, consumidores idempotentes que puedan procesar el mismo mensaje sin efectos secundarios adicionales.
Autenticación: verificar que el usuario es quien dice ser (JWT, session, API key). Autorización: verificar que el usuario autenticado tiene permiso para realizar la acción solicitada. Se implementan en capas: middleware de autenticación primero (valida el token), luego guards de autorización por endpoint o recurso que evalúan roles o políticas.
Evitar offset pagination a gran escala porque es ineficiente (la BD debe contar y saltar registros). Preferir cursor-based pagination: el cliente envía el ID o timestamp del último elemento recibido, y la query usa WHERE id > cursor LIMIT n. Es O(log n) con índice en lugar de O(n), y funciona correctamente con inserciones concurrentes.

Preguntas técnicas

En multi-tenant, además de autenticar la identidad, se debe resolver a qué tenant pertenece el usuario y qué puede hacer dentro de ese tenant. Implica incluir el tenant_id en el token, aislar datos por tenant a nivel de query (row-level security en PostgreSQL o filtros obligatorios en el ORM), y definir si los permisos son globales o por tenant.
N+1 ocurre cuando se ejecuta una query por cada elemento de una lista en lugar de una sola query con JOIN o batch. Prevención: eager loading configurado en el ORM, DataLoader para GraphQL, o queries explícitas con JOINs. Diagnóstico: logging de queries con slow query log, APM tools, o instrumentación manual contando queries por request.
Implementar circuit breakers para evitar cascada de fallos. Definir tiempos de timeout explícitos por servicio. Separar errores recuperables (reintentos con backoff exponencial) de errores permanentes. Usar el patrón saga o compensating transactions para operaciones distribuidas que requieren rollback. Loggear con correlation IDs para trazar errores entre servicios.
ORM: mayor productividad, protección contra SQL injection por defecto, portabilidad entre motores. Con ORMs se pierden optimizaciones específicas del motor, es fácil generar queries ineficientes sin darse cuenta, y el debugging requiere entender qué SQL genera. Para casos de alto tráfico con queries complejas, combinar ORM para CRUD simple con SQL nativo para queries críticas de rendimiento.
Elegir estrategia según el patrón de acceso: cache-aside (el código gestiona el caché), write-through (se escribe en caché y BD simultáneamente) o read-through. La invalidación es el problema harder: opciones son TTL fijo, invalidación por evento (cuando se actualiza el dato) o cache-bust por versión. Evitar cachear datos que cambian frecuentemente o que tienen alta cardinalidad de claves.
Dentro de una BD: transacciones ACID con BEGIN/COMMIT. Entre servicios: el patrón saga con orquestación o coreografía, donde cada paso emite un evento y en caso de fallo se ejecutan transacciones compensatorias. El patrón outbox garantiza que el evento y la escritura en BD ocurran atómicamente evitando el problema de 'escribí en BD pero no emití el evento'.
Validar tipo de archivo por magic bytes, no por extensión. Limitar tamaño. Nunca almacenar archivos con el nombre original del usuario. Ejecutar el procesamiento en un proceso aislado o sandbox. Si los archivos son servidos públicamente, hacerlo desde un dominio separado para prevenir XSS. Escanear con antivirus si el contexto lo requiere. Nunca ejecutar archivos subidos.
Versionado en URL (/v1/, /v2/) es el más explícito y fácil de enrutar. Versionado por header (Accept: application/vnd.api+json;version=2) es más RESTful pero más complejo de implementar y documentar. Adoptar una política de deprecación clara: anunciar con anticipación, mantener versiones antiguas por un período definido, y ofrecer guías de migración. Nunca introducir breaking changes en una versión existente.

Preguntas avanzadas

Primero identificar el bottleneck con profiling: ¿es CPU, I/O de BD, memoria o red? Escalar horizontalmente con load balancer si el bottleneck es CPU. Añadir réplicas de lectura si es carga de BD lectora. Implementar caching agresivo para queries frecuentes. Evaluar si operaciones síncronas pueden moverse a colas. Como último recurso, reevaluar el modelo de datos o la arquitectura de la query más costosa.
El primer error es descomponer demasiado pronto. Identificar bounded contexts con alta cohesión interna y bajo acoplamiento entre sí. Extraer primero los servicios que más se benefician de escala o deploy independiente. El mayor costo es la comunicación distribuida: latencia, consistencia eventual, y observabilidad. Preparar la infraestructura de observabilidad (tracing distribuido, centralización de logs) antes de descomponer.
Usar un identity provider centralizado (Auth0, Keycloak, o propio) que emita tokens con claims de tenant y roles. Implementar OIDC para SSO. Los permisos granulares (ABAC) se evalúan en cada servicio usando los claims del token más el contexto del recurso solicitado. Cachear las decisiones de autorización con TTL corto. Auditar todos los accesos a recursos sensibles.
Los tres pilares: logs estructurados (JSON) con correlation ID que atraviesa todos los servicios, métricas con percentiles p95/p99 de latencia y error rate, y distributed tracing con OpenTelemetry. Para fallos intermitentes, las métricas alertan, el tracing muestra en qué servicio y operación falla, y los logs dan el contexto del error. Sin los tres, el debugging en producción es especulativo.
Cifrado en tránsito (TLS 1.3) y en reposo para datos sensibles. Principio de mínimo privilegio en credenciales de BD. Evitar logs con PII. Sanitizar inputs para prevenir SQL injection, XSS y path traversal. Implementar rate limiting y abuse detection. Rotar secretos automáticamente con un gestor de secretos (Vault, AWS Secrets Manager). Realizar threat modeling periódicamente y penetration testing en cambios de arquitectura.
Usar una cola persistente (Redis con AOF, SQS, o Kafka) en lugar de colas en memoria. Implementar el patrón outbox para encolado atómico con la escritura en BD. Diseñar workers idempotentes que puedan re-procesar el mismo mensaje sin efectos secundarios. Definir una dead letter queue para tareas que fallan repetidamente. Monitorear el lag de la cola como métrica de salud del sistema.

Errores comunes en entrevistas

Decir 'usé microservicios' o 'implementé caché' sin explicar qué problema resolvía, qué alternativas evaluaste y qué compromisos aceptaste demuestra pensamiento en modo receta, no en modo ingeniero. Los entrevistadores de nivel senior siempre van a preguntar '¿y por qué esa solución y no X?'.
Cualquier diseño de API, sistema de autenticación o procesamiento de datos que no mencione autenticación, autorización, validación de inputs o manejo de secretos es una señal de alerta. En roles backend la seguridad es parte del diseño, no un paso separado.
Proponer Kafka, Kubernetes y sharding de BD para una aplicación con 1000 usuarios diarios es una señal de over-engineering. Los entrevistadores evalúan si el candidato puede calibrar la complejidad de la solución al tamaño real del problema.
Muchos desarrolladores usan ORMs sin entender el SQL subyacente. En entrevistas de backend con foco en rendimiento, no poder explicar qué query se ejecuta detrás de una operación frecuente, o no haber usado EXPLAIN ANALYZE, es una debilidad notable.
Es frecuente que los candidatos describan sistemas distribuidos sin entender qué garantías de consistencia ofrecen realmente. Decir 'eventualmente consistente' sin explicar qué escenarios de inconsistencia son aceptables y cuáles no, genera dudas sobre la comprensión real del sistema.
Un sistema que funciona en desarrollo pero no tiene logs estructurados, métricas, health checks o una estrategia de deploy es un sistema incompleto. Los entrevistadores de empresas con sistemas en producción real consideran la observabilidad y el deployment como parte del diseño, no como un afterthought.