{
 "meta": {
  "titulo": "Flashcards · Examen Técnico",
  "subtitulo": "Java · Spring Boot · GCP · Microservicios",
  "autor": "Kit de estudio"
 },
 "categorias": [
  {
   "id": "java",
   "prefijo": "J",
   "nombre": "Java",
   "color": "#E76F00"
  },
  {
   "id": "spring",
   "prefijo": "S",
   "nombre": "Spring Boot",
   "color": "#3E8E41"
  },
  {
   "id": "gcp",
   "prefijo": "G",
   "nombre": "GCP",
   "color": "#1A73E8"
  },
  {
   "id": "micro",
   "prefijo": "M",
   "nombre": "Microservicios",
   "color": "#7B1FA2"
  }
 ],
 "chuleta": [
  "Verbos HTTP: GET leer · POST crear · PUT reemplaza · PATCH parcial · DELETE borra. Idempotentes: GET/PUT/DELETE. Seguro: GET.",
  "Códigos HTTP: 200 OK · 201 Created (+Location) · 204 sin body · 400 validación · 401 no autenticado · 403 sin permiso · 404 no existe · 409 conflicto · 429 rate limit · 500 bug · 503 caído.",
  "ACID: Atomicidad, Consistencia, Aislamiento, Durabilidad. CAP: ante partición (P) eliges consistencia (C) o disponibilidad (A).",
  "Escalera REST (Richardson): 0 RPC/POX · 1 recursos · 2 verbos + códigos HTTP · 3 HATEOAS.",
  "JWT: header.payload.signature; firma HS256 (simétrica) o RS256 (asimétrica). Claims clave: sub, iss, aud, exp, iat. Nunca guardar datos sensibles: es legible (base64).",
  "OAuth2: Authorization Code + PKCE para apps/SPA · Client Credentials para servicio-a-servicio · Refresh Token para renovar sin re-login.",
  "SQL rápido: índices B-tree aceleran WHERE/JOIN · EXPLAIN para ver el plan · N+1 se resuelve con JOIN FETCH / batch · paginar con keyset, no solo OFFSET.",
  "Concurrencia en BD: optimista = @Version + retry (mejor para poca contención) · pesimista = SELECT FOR UPDATE (contención alta).",
  "Pool de conexiones: HikariCP (default en Boot). Ajustar maximumPoolSize (10-20 suele bastar) y connectionTimeout.",
  "Caché HTTP: Cache-Control (max-age, no-cache) + ETag/If-None-Match → 304 Not Modified. Caché de app: Spring @Cacheable.",
  "JUnit 5: @Test, @BeforeEach, AssertJ assertThat. Mockito: @Mock + @InjectMocks. Tipos de test Spring: @WebMvcTest (capa web), @DataJpaTest (repositorios), @SpringBootTest (integración completa).",
  "TDD: rojo (test que falla) → verde (código mínimo) → refactor. Pirámide: muchos unit, algunos integration, pocos E2E.",
  "SOLID: S una razón de cambio por clase · O abierto a extensión, cerrado a modificación · L subtipos sustituibles · I interfaces pequeñas · D depender de abstracciones.",
  "GoF que salen siempre: Singleton, Factory Method, Builder, Strategy, Adapter, Observer, Decorator, Proxy (Spring AOP usa proxies dinámicos).",
  "Maven: coordenadas groupId:artifactId:version · scopes: compile, provided, runtime, test · BOM para alinear versiones · mvnw wrapper para versionar Maven.",
  "Docker: imagen inmutable por capas con cache · multi-stage build para imagen liviana · no correr como root · ENTRYPOINT vs CMD · healthcheck.",
  "Kubernetes: Pod (unidad mínima) · Deployment (réplicas + rolling update) · Service (IP estable/DNS) · Ingress (rutas HTTP) · HPA (autoescalado) · ConfigMap/Secret (config).",
  "Logging: niveles TRACE < DEBUG < INFO < WARN < ERROR. Estructurado (JSON) y con correlation ID. Nunca datos personales ni secretos en logs.",
  "CORS: el navegador lanza preflight OPTIONS; el servidor responde con Access-Control-Allow-Origin/Methods/Headers. Es un mecanismo del navegador, no del servidor.",
  "Git/entrega: feature branches + Pull Request · squash merge · Conventional Commits (feat/fix/chore) · SemVer MAYOR.MINOR.PATCH (mayor = rompe compatibilidad).",
  "Rate limiting: 429 Too Many Requests + header Retry-After. Algoritmos: token bucket, sliding window. Se aplica en gateway.",
  "Async en Spring: @Async + @EnableAsync (executor), @EventListener para eventos en proceso, CompletableFuture para composición.",
  "Programación reactiva (WebFlux): Mono (0..1) y Flux (0..N), backpressure, no bloquea hilos; útil con mucha I/O concurrente. MVC por hilos sigue siendo válido para CRUD normal.",
  "Microservicios: contrato primero (OpenAPI), consumer-driven contract tests (Pact), CI/CD por servicio, feature flags para desacoplar deploy de release.",
  "En la nube: 12-factor (config en entorno, procesos stateless, logs como stream), probes de salud, escalado horizontal primero, idempotencia en todo endpoint que escribe.",
  "K8s probes: liveness reinicia el pod, readiness lo saca del balanceo, startup da margen a arranques lentos. Requests/limits de CPU-memoria definen la calidad de servicio.",
  "JOINs SQL: INNER (solo coincidencias) · LEFT (toda la izquierda + coincidencias) · RIGHT · FULL. Subconsultas correlacionadas fila a fila = sospechar de N+1.",
  "HTTP/2: multiplexa streams en una conexión, comprime headers (HPACK) y permite prioridades; gRPC exige HTTP/2. HTTP/3 va sobre QUIC/UDP.",
  "Complejidad: HashMap get/put O(1) medio · búsqueda binaria O(log n) · ordenar O(n log n) · recorrer O(n). ArrayList contains O(n).",
  "Colecciones thread-safe: ConcurrentHashMap (no bloquea el mapa entero) · CopyOnWriteArrayList (muchas lecturas) · BlockingQueue (productor/consumidor).",
  "Bean Validation: @Valid en el parámetro + @NotNull/@Size/@Email/@Pattern en el DTO; si falla, MethodArgumentNotValidException → 400 con detalles.",
  "Clientes REST en Spring: RestClient (síncrono, moderno) · WebClient (reactivo) · OpenFeign (declarativo por interfaz). Configura siempre timeout y retry.",
  "Docker Compose levanta el stack local (app + BD + cola) con docker compose up; perfiles para servicios opcionales. En prod: Kubernetes o Cloud Run.",
  "GCP rápido: proyecto = unidad de facturación/IAM · región (multi-zona) vs zona · Cloud Run = contenedor serverless · Pub/Sub = at-least-once · IAM = least privilege · ADC para autenticar apps sin claves."
 ],
 "tarjetas": [
  {
   "cat": "java",
   "q": "¿Diferencia entre JDK, JRE y JVM?",
   "a": "JVM: ejecuta el bytecode (.class) y da independencia de plataforma.\nJRE = JVM + librerías para EJECUTAR programas.\nJDK = JRE + herramientas para DESARROLLAR (javac, javadoc, jdb).\nDesarrollas con JDK; ejecutas con JRE.",
   "sub": "JVM y rendimiento",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "java",
   "q": "¿Cómo funciona el Garbage Collector?",
   "a": "Rastrea objetos alcanzables desde las raíces (hilos, static); lo no alcanzable se elimina del heap.\nHeap generacional: Young (Eden + Survivor, GCs menores) y Old (GC major).\nSystem.gc() solo es una sugerencia: no garantiza nada.",
   "sub": "JVM y rendimiento",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "java",
   "q": "Stack vs Heap",
   "a": "Stack: por hilo, guarda frames de métodos y variables locales/primitivas (LIFO, muy rápido).\nHeap: compartido, guarda objetos y arrays; lo gestiona el GC.\nOutOfMemoryError → heap. StackOverflowError → recursión sin fin.",
   "sub": "JVM y rendimiento",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "java",
   "q": "¿Por qué String es inmutable?",
   "a": "Su contenido no cambia tras crearse (los métodos devuelven nuevos Strings).\nBeneficios:\n• String pool reutiliza instancias\n• Thread-safe\n• hashCode cacheado\n• Seguro como clave en HashMap y para rutas/URLs",
   "sub": "String y texto",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "java",
   "q": "== vs equals() vs hashCode()",
   "a": "== compara referencias (mismo objeto en memoria).\nequals() compara estado; se sobrescribe junto a hashCode.\nContrato: si a.equals(b), entonces a.hashCode() == b.hashCode().\nSi no cumples el contrato, HashMap/HashSet se rompen.",
   "sub": "POO",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "java",
   "q": "¿Cómo funciona HashMap internamente?",
   "a": "Array de buckets; índice = hash(key) & (n-1).\nColisiones: lista enlazada; desde Java 8 se balancea como árbol rojo-negro si el bucket llega a 8.\nCapacidad inicial 16, factor de carga 0.75 → resize duplica.\nClaves únicas; una clave null permitida.",
   "sub": "Colecciones",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "java",
   "q": "ArrayList vs LinkedList",
   "a": "ArrayList: array dinámico; get por índice O(1); insertar/borrar en medio O(n) (desplaza elementos).\nLinkedList: doblemente enlazada; add/remove en extremos O(1); get O(n).\nEn la práctica gana ArrayList casi siempre (localidad de caché).",
   "sub": "Colecciones",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "java",
   "q": "List vs Set vs Map",
   "a": "List: ordenada, con índices, permite duplicados (ArrayList, LinkedList).\nSet: SIN duplicados (HashSet, TreeSet ordena por comparación).\nMap: pares clave→valor, claves únicas; no hereda de Collection (HashMap, TreeMap).",
   "sub": "Colecciones",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "java",
   "q": "¿Interfaz vs clase abstracta?",
   "a": "Interfaz: contrato puro; métodos abstract + default/static (Java 8+); una clase implementa varias.\nClase abstracta: no instanciable; tiene estado (campos), constructores y código común; herencia simple.\nInterfaz para capacidad ('puede...'); abstracta para compartir estado.",
   "sub": "POO",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "java",
   "q": "Checked vs unchecked exceptions",
   "a": "Checked (heredan de Exception): el compilador obliga a capturarlas o declararlas con throws — IOException, SQLException.\nUnchecked (heredan de RuntimeException): no obliga — NullPointerException, IllegalArgumentException.\nError: fallos fatales de JVM (OutOfMemoryError).",
   "sub": "Excepciones",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "java",
   "q": "¿Qué hace try-with-resources?",
   "a": "Cierra automáticamente cualquier recurso que implemente AutoCloseable al salir del bloque, incluso si hay excepción.\nElimina el finally con close().\nSi fallan el bloque y el close(), la del close() viaja como 'suppressed' adjunta a la principal.",
   "sub": "Excepciones",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "java",
   "q": "final / finally / finalize",
   "a": "final: no se puede cambiar — variable (constante), método (no sobrescribible), clase (no heredable).\nfinally: bloque tras try/catch que casi siempre se ejecuta (limpieza).\nfinalize(): lo llama el GC antes de liberar el objeto; deprecado — no confíes en él.",
   "sub": "Sintaxis y tipos",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "java",
   "q": "¿Qué son los Streams de Java 8?",
   "a": "Pipeline funcional sobre colecciones:\nfuente → intermedias PEREZOSAS (filter, map, sorted) → TERMINAL (collect, forEach, reduce) que dispara la evaluación.\nNo mutan la fuente.\nparallelStream() para procesar en paralelo (cuidado con orden y threads).",
   "sub": "Streams y lambdas",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "java",
   "q": "¿Para qué sirve Optional?",
   "a": "Contenedor que expresa 'puede no haber valor' en el tipo de retorno; evita null y NPE.\nMétodos: map, filter, orElse / orElseGet, orElseThrow, ifPresent.\nAntipatrón: Optional como campo o parámetro.\nNunca .get() sin comprobar.",
   "sub": "Streams y lambdas",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "java",
   "q": "volatile vs synchronized",
   "a": "volatile: garantiza VISIBILIDAD (las escrituras de un hilo se ven al instante) pero NO atomicidad — i++ sigue roto.\nsynchronized: exclusión mutua + visibilidad mediante lock de monitor; bloquea un método o bloque.",
   "sub": "Concurrencia",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "java",
   "q": "¿Qué es ExecutorService?",
   "a": "Pool de hilos que ejecuta tareas sin crear hilos a mano.\nEnvías Callable/Runnable y recibes Future con el resultado.\nFábricas: newFixedThreadPool, newCachedThreadPool, newScheduledThreadPool.\nSiempre cerrarlo: shutdown() / shutdownNow().",
   "sub": "Concurrencia",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "java",
   "q": "¿Qué añade CompletableFuture sobre Future?",
   "a": "Composición NO bloqueante:\n• thenApply / thenCompose / thenCombine encadenan etapas\n• callbacks sin .get() bloqueante\n• errores con exceptionally / handle\n• combina tareas paralelas\nEs la base de la programación asíncrona en Java moderno.",
   "sub": "Concurrencia",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "java",
   "q": "¿Qué es un record (Java 14+)?",
   "a": "Clase inmutable de datos en una línea:\nrecord Point(int x, int y) {}\nGenera constructor, accesores (x(), y()), equals, hashCode y toString.\nNo puede extender otras clases. Ideal para DTOs y valores.",
   "sub": "Java moderno",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "java",
   "q": "Overloading vs Overriding",
   "a": "Overloading (sobrecarga): mismo nombre, distinta firma (parámetros); se resuelve en COMPILACIÓN.\nOverriding (sobreescritura): redefinir un método heredado con la misma firma; se resuelve en EJECUCIÓN según el tipo real del objeto (dynamic dispatch → polimorfismo).",
   "sub": "POO",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "java",
   "q": "¿Qué hace static?",
   "a": "El miembro pertenece a la CLASE, no a cada instancia: compartido por todos los objetos y usable sin instanciar.\nClase anidada static: no guarda referencia al exterior.\nBloque static: inicialización una sola vez al cargar la clase.",
   "sub": "POO",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "¿Qué es Spring Boot y qué aporta?",
   "a": "Capa opinionada sobre Spring que elimina la configuración manual:\n• Autoconfiguración según el classpath\n• Starters (spring-boot-starter-web)\n• Servidor embebido (Tomcat/Jetty)\n• Actuator listo para producción\n@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan.",
   "sub": "Boot y starters",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "¿Cómo funciona la autoconfiguración?",
   "a": "@EnableAutoConfiguration carga configuraciones candidatas que se activan SOLO si se cumplen condiciones:\n@ConditionalOnClass, @ConditionalOnMissingBean, @ConditionalOnProperty.\nEj.: detecta H2 en el classpath → configura un DataSource.\nSe excluye con exclude=... en @SpringBootApplication.",
   "sub": "Boot y starters",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "¿Qué son IoC y la inyección de dependencias?",
   "a": "IoC: el contenedor (ApplicationContext) crea, cablea y gestiona el ciclo de vida de los beans; tú no haces new.\nDI: las dependencias llegan inyectadas (constructor > setter > campo).\nBeneficios: bajo acoplamiento, testeo con mocks, cambiar implementaciones fácil.",
   "sub": "Núcleo IoC",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "@Component vs @Service vs @Repository vs @Controller",
   "a": "Son estereotipos: todas registran un bean.\n@Component: genérico.\n@Service: lógica de negocio (semántica).\n@Repository: traduce excepciones de persistencia a DataAccessException.\n@Controller: capa web. @RestController = @Controller + @ResponseBody (JSON).",
   "sub": "Núcleo IoC",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "¿Por qué inyectar por constructor y no por campo?",
   "a": "Constructor:\n• dependencias obligatorias explícitas\n• campos pueden ser final\n• testeable sin Spring (new + mocks)\n• detecta dependencias circulares al arrancar.\n@Autowired en campo: oculta dependencias y exige reflejo en tests. Spring recomienda constructor.",
   "sub": "Núcleo IoC",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "@Bean vs @Component",
   "a": "@Component: sobre TU clase; se registra por escaneo de componentes.\n@Bean: método dentro de @Configuration que DEVUELVE la instancia; para clases de terceros que no puedes anotar.\n@Configuration con proxy de métodos reutiliza llamadas a @Bean (respeta singleton).",
   "sub": "Núcleo IoC",
   "nivel": "basico",
   "clave": false
  },
  {
   "cat": "spring",
   "q": "Scopes de beans en Spring",
   "a": "singleton (default): una instancia por contenedor.\nprototype: nueva por cada petición/inyección.\nrequest, session, websocket: por contexto web.\nTrampa: inyectar prototype dentro de un singleton se resuelve UNA vez → usar ObjectProvider o @Lookup.",
   "sub": "Núcleo IoC",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "Ciclo de vida de un bean",
   "a": "Instanciación → inyección de dependencias → callbacks Aware → BeanPostProcessor (before) → @PostConstruct → afterPropertiesSet → LISTO → al cerrar: @PreDestroy.\nLos BeanPostProcessors envuelven los beans: así funcionan @Transactional, @Async, @Lazy.",
   "sub": "Núcleo IoC",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "@Controller vs @RestController",
   "a": "@Controller: devuelve nombres de VISTA (HTML con Thymeleaf, etc.).\n@RestController: añade @ResponseBody → cada método retorna el objeto que Spring serializa a JSON con HttpMessageConverters (Jackson).\nPara APIs REST: siempre @RestController.",
   "sub": "Web MVC y REST",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "Flujo de una petición en Spring MVC",
   "a": "Request → DispatcherServlet (front controller) → HandlerMapping elige el método → interceptores → argumentos resueltos (@PathVariable, @RequestBody...) → tu método → HttpMessageConverter serializa → respuesta.\nExcepciones → @ExceptionHandler / @ControllerAdvice.",
   "sub": "Web MVC y REST",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "@PathVariable vs @RequestParam vs @RequestBody",
   "a": "@PathVariable: del path → GET /users/{id}\n@RequestParam: query string → ?page=2&size=10 (defaultValue, required)\n@RequestBody: deserializa el body (JSON → DTO) en POST/PUT.\n@RequestHeader para cabeceras.",
   "sub": "Web MVC y REST",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "¿Qué es JPA? ¿Y Hibernate? ¿Y Spring Data JPA?",
   "a": "JPA: especificación de ORM en Java (mapear entidades con @Entity, @Id, relaciones).\nHibernate: implementación de referencia.\nSpring Data JPA: capa encima que genera repositorios (JpaRepository) y queries por nombre de método (findByEmail) o @Query.",
   "sub": "Spring Data JPA",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "Estados de una entidad JPA",
   "a": "Transient: nuevo, fuera del contexto.\nManaged: attached — el dirty checking detecta cambios y los sincroniza en flush (sin llamar a save).\nDetached: el contexto cerró; save() hace merge para re-adjuntar.\nRemoved: marcado para DELETE.",
   "sub": "Spring Data JPA",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "@Transactional: ¿cómo funciona y qué trampas tiene?",
   "a": "AOP crea un proxy que abre/commit/rollback la transacción.\nRollback SOLO con RuntimeException por defecto (usa rollbackFor=Exception.class).\nNO funciona: self-invocation (this.metodo()), métodos private/static.\nPropagación: REQUIRED (une tx existente), REQUIRES_NEW (suspende y crea nueva), NESTED.",
   "sub": "Transacciones",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "cat": "spring",
   "q": "Niveles de aislamiento de transacciones",
   "a": "READ_UNCOMMITTED: lee datos sin confirmar (dirty read).\nREAD_COMMITTED: solo datos confirmados (default Postgres/Oracle).\nREPEATABLE_READ: lecturas repetibles (default MySQL/InnoDB).\nSERIALIZABLE: como ejecución en serie.\nMás aislamiento → menos anomalías, más bloqueos.",
   "sub": "Transacciones",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "cat": "spring",
   "q": "¿Qué es LazyInitializationException y cómo se evita?",
   "a": "Acceder a una relación LAZY cuando la sesión de Hibernate ya cerró.\nSoluciones:\n• JOIN FETCH en JPQL (@Query)\n• @EntityGraph\n• proyecciones a DTO\n• transacción abierta en el servicio (evita depender de open-in-view).",
   "sub": "Spring Data JPA",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "¿Cómo manejas excepciones globalmente en una API?",
   "a": "@RestControllerAdvice con métodos @ExceptionHandler(Excepcion.class): mapean excepciones de toda la app a respuestas HTTP uniformes (status + cuerpo de error).\nSpring 6 trae ProblemDetail (RFC 7807).\n@ResponseStatus para casos simples.",
   "sub": "Web MVC y REST",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "application.properties, YAML y profiles",
   "a": "Config externa en application.properties / .yml.\nProfiles: application-prod.yml + spring.profiles.active=prod; activan beans con @Profile.\nPrecedencia: variables de entorno y args de CLI > perfiles > application.yml base.",
   "sub": "Configuración",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "¿Qué ofrece Spring Boot Actuator?",
   "a": "Endpoints de operación:\n/actuator/health (con liveness/readiness), /metrics (JVM, HTTP, pools), /info, /env, /prometheus (exporter para Grafana).\nSe exponen con management.endpoints.web.exposure.include.\nBase del monitoreo y de los probes de K8s.",
   "sub": "Producción y observabilidad",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "spring",
   "q": "¿Qué es un Circuit Breaker (Resilience4j)?",
   "a": "Patrón anti-cascada: si un servicio remoto falla N veces, el circuito se ABRE y falla rápido sin llamarlo (fallback); tras un tiempo pasa a HALF-OPEN y prueba de nuevo; si funciona, se CIERRA.\n@CircuitBreaker(name=\"servicio\", fallbackMethod=\"respaldo\").",
   "sub": "Spring Cloud y resiliencia",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "Compute Engine vs App Engine vs Cloud Run vs GKE",
   "a": "Compute Engine: VMs (IaaS), control total — lift & shift.\nApp Engine: PaaS clásico (standard/flexible).\nCloud Run: contenedor serverless, escala a 0, pagas por uso.\nGKE: Kubernetes gestionado para orquestar muchos microservicios.\nServerless simple → Cloud Run; control de clúster → GKE.",
   "sub": "Compute y contenedores",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "¿Cuándo elegirías Cloud Run?",
   "a": "Cuando empaquetas la app en un contenedor Docker sin gestionar infraestructura: APIs HTTP, webhooks, microservicios, eventos.\nEscala automático a 0 (no pagas en reposo) hasta N instancias; concurrencia por instancia configurable.\nDebe ser stateless y escuchar en la variable $PORT.",
   "sub": "Compute y contenedores",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "Cloud Storage: clases y lifecycle",
   "a": "Standard: acceso frecuente.\nNearline: ~1 acceso/mes. Coldline: ~1 cada 90 días. Archive: retención larga (lo más barato).\nMulti-region para HA; region para menor costo.\nLifecycle rules automáticas: degradar clase, borrar versiones viejas. Versioning y retención.",
   "sub": "Almacenamiento",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "Pub/Sub: modelo y garantías de entrega",
   "a": "Publisher → topic → subscription → subscriber (pull o push).\nEntrega AT-LEAST-ONCE: puede duplicar → el consumidor debe ser idempotente.\nAck deadline: si no confirmas, se reenvía.\nDead-letter topic tras N intentos fallidos. Ordering keys para orden por clave.",
   "sub": "Mensajería y eventos",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "¿Qué base de datos GCP elijo? (SQL vs Firestore vs Spanner vs Bigtable vs BigQuery)",
   "a": "Cloud SQL: relacional gestionado (MySQL/Postgres/SQL Server) — apps transaccionales.\nFirestore: NoSQL documentos, tiempo real (móvil/web).\nSpanner: SQL distribuido GLOBAL con consistencia fuerte.\nBigtable: NoSQL wide-column, time-series/IoT, throughput masivo.\nBigQuery: analítica OLAP sobre petabytes (serverless).",
   "sub": "Bases de datos",
   "nivel": "avanzado",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "¿Cómo funciona IAM en GCP?",
   "a": "Policy = QUIÉN (member) con qué ROL sobre qué RECURSO.\nMembers: usuarios, grupos, service accounts.\nRoles: básicos (Owner/Editor/Viewer, muy amplios), predefinidos (granulares: roles/pubsub.publisher), custom.\nSe hereda por la jerarquía org → carpeta → proyecto.\nPrincipio: least privilege.",
   "sub": "IAM y seguridad",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "Service Accounts: ¿qué son y cómo se usan bien?",
   "a": "Identidad para CÓDIGO, no personas (email: sa@proyecto.iam.gserviceaccount.com).\nA cada workload (Cloud Run, GKE, Compute) le adjuntas una SA con roles mínimos; la app autentica con ADC sin claves.\nEvita descargar JSON keys; si son inevitables: rotar y guardar en Secret Manager.\nImpersonation (actAs) para tareas puntuales.",
   "sub": "IAM y seguridad",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "cat": "gcp",
   "q": "VPC, subredes y firewall rules",
   "a": "VPC: red privada GLOBAL; subredes REGIONALES con rangos CIDR.\nFirewall: reglas stateful allow/deny por prioridad, aplican a targets (tags de red o service accounts).\nConectar VPCs: VPC Peering o Shared VPC.\nPrivate Google Access: llegar a las APIs de Google sin IP externa.",
   "sub": "Redes",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "Cloud Load Balancing y Cloud CDN",
   "a": "Balanceador global anycast HTTP(S) L7 (o L4): terminación SSL, URL maps que enrutan por path/host a backend services (VMs, serverless NEG, Storage).\nCloud CDN cachea en edge POPs cerca del usuario.\nCloud Armor añade WAF y protección anti-DDoS.",
   "sub": "Redes",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "CI/CD en GCP: Cloud Build + Artifact Registry",
   "a": "Cloud Build: ejecuta pipelines definidos en cloudbuild.yaml (build, test, push, deploy) con triggers desde Git.\nArtifact Registry: almacén de imágenes Docker y paquetes (npm, Maven, Python) con IAM y análisis de vulnerabilidades.\nFlujo típico: build → push imagen → gcloud run deploy.",
   "sub": "DevOps y CI/CD",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "¿Para qué sirve Secret Manager?",
   "a": "Bóveda central de secretos (API keys, passwords, tokens) con versionado, IAM por secreto, rotación, auditoría y replicación.\nLa app lee secretos en runtime con la client library usando ADC.\nNada de secretos hardcodeados ni en variables de entorno planas.",
   "sub": "IAM y seguridad",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "Cloud Functions vs Cloud Run",
   "a": "Cloud Functions: FaaS — función suelta disparada por evento (HTTP, Pub/Sub, Storage); la 2ª generación corre sobre Cloud Run.\nCloud Run: contenedor completo (cualquier runtime/framework), más control, alta concurrencia por instancia.\nRegla: una función pequeña → Functions; una app/servicio → Run.",
   "sub": "Serverless",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "Jerarquía de recursos en GCP",
   "a": "Organization → Folders → Projects → Resources.\nLos proyectos aíslan facturación, cuotas, IAM y APIs habilitadas.\nLas políticas (IAM y org policies) se HEREDAN hacia abajo.\nBuena práctica: un proyecto por entorno (dev/stage/prod) o dominio, carpetas por equipo.",
   "sub": "Fundamentos y organización",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "Cloud Operations: Logging, Monitoring, Trace",
   "a": "Logging: logs centralizados de todos los servicios, consultas, sinks a BigQuery/Storage, log-based metrics.\nMonitoring: dashboards, uptime checks, alert policies y SLOs.\nCloud Trace: distributed tracing de latencias entre servicios.\nProfiler: uso continuo de CPU/memoria.",
   "sub": "Observabilidad y SRE",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "¿Para qué sirve Memorystore?",
   "a": "Redis / Memcached gestionado en memoria:\n• caché de resultados y sesiones\n• rate limiting\n• colas ligeras\nReduce latencia (sub-milisegundos) y carga sobre Cloud SQL/Firestore.\nTiers: Basic (sin HA) vs Standard (con réplica). Configurar eviction (allkeys-lru) y TTLs.",
   "sub": "Bases de datos",
   "nivel": "basico",
   "clave": false
  },
  {
   "cat": "gcp",
   "q": "¿Cómo conecto Cloud Run/GKE con recursos privados?",
   "a": "Serverless VPC Access connector (Cloud Run/Functions) para alcanzar la VPC privada: VMs, Memorystore, Cloud SQL con IP privada.\nGKE habla nativamente con la VPC.\nCloud SQL Auth Proxy o conectores IAM para bases de datos.\nPrivate Service Connect: consumir servicios gestionados por IP privada.",
   "sub": "Redes",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "Autenticación de usuarios finales vs de servicios",
   "a": "IAM autentica administradores y service accounts.\nPara usuarios FINALES de tu app: Identity Platform / Firebase Auth (email, Google, OAuth federado) emite JWTs que tu backend valida (firma + audience).\nAPI Gateway / Cloud Endpoints pueden validar JWTs antes de llegar a tu servicio.",
   "sub": "IAM y seguridad",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "cat": "gcp",
   "q": "¿Qué es Application Default Credentials (ADC)?",
   "a": "Mecanismo estándar de autenticación: las client libraries buscan credenciales en orden:\n1. GOOGLE_APPLICATION_CREDENTIALS (archivo)\n2. SA adjunta al entorno (metadata server en Cloud Run/GKE/Compute)\n3. credenciales de gcloud en local.\nAsí el MISMO código corre en local y en GCP sin claves en el código.",
   "sub": "IAM y seguridad",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "Presupuestos y optimización de costos en GCP",
   "a": "Budgets con alertas (email/Pub/Sub) · labels para atribuir costo por equipo/app · informes de Billing.\nAhorro: committed use discounts (1-3 años), VMs Spot para carga interrumpible, apagar dev de noche, right-sizing recommendations, Cloud Run escala a 0.",
   "sub": "Fundamentos y organización",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "gcp",
   "q": "¿Qué es un 'proyecto' en GCP?",
   "a": "Unidad base de organización: dentro viven todos los recursos; define cuotas, facturación, IAM base y qué APIs están habilitadas.\nCada recurso pertenece exactamente a un proyecto.\nPatrón habitual: proyectos separados por entorno (dev/stage/prod) bajo la misma organización.",
   "sub": "Fundamentos y organización",
   "nivel": "basico",
   "clave": false
  },
  {
   "cat": "micro",
   "q": "¿Monolito o microservicios?",
   "a": "Monolito: un solo deployable; dev/debug/transacciones simples; escala todo junto y acopla módulos.\nMicroservicios: servicios pequeños, desplegables y escalables por separado; equipos independientes.\nCosto: complejidad distribuida (red, consistencia eventual, observabilidad).\nEmpieza modular; divide cuando duela.",
   "sub": "Fundamentos y decisiones",
   "nivel": "basico",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "¿Cómo divides en microservicios? (Bounded Context)",
   "a": "Por dominio de NEGOCIO, no por capas técnicas (DDD): cada Bounded Context (Pedidos, Pagos, Inventario) tiene su modelo y lenguaje; el servicio posee sus datos.\nSeñales: cambios que van juntos, equipos distintos, escalado distinto.\nAnti-patrón: nanoservicios CRUD que comparten BD.",
   "sub": "Fundamentos y decisiones",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "Comunicación síncrona vs asíncrona",
   "a": "Síncrona (REST, gRPC): el llamador espera; acopla en el tiempo (si el destino cae, falla).\nAsíncrona (Pub/Sub, Kafka): eventos/mensajes; desacopla en el tiempo, absorbe picos, más resiliente; pero consistencia eventual.\nMezcla habitual: comandos críticos sync + eventos async para propagar cambios.",
   "sub": "Comunicación",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "REST vs gRPC",
   "a": "REST: recursos + verbos HTTP, JSON legible, cacheable, tooling universal — ideal para APIs públicas.\ngRPC: HTTP/2 + Protobuf binario, contratos tipados (.proto), streaming bidireccional, mucho más rápido — ideal interno servicio-a-servicio.\nREST se documenta con OpenAPI; gRPC genera código cliente/servidor.",
   "sub": "Comunicación",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "¿Qué es un API Gateway y qué responsabilidades tiene?",
   "a": "Puerta única de entrada para clientes externos:\nrouting, autenticación/autorización (JWT), rate limiting, TLS, caché, agregación, CORS, versionado.\nImplementaciones: Spring Cloud Gateway, Kong, Apigee.\nMantiene los cross-cutting concerns fuera de los microservicios.",
   "sub": "APIs y edge",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "Service Discovery: ¿por qué y cómo?",
   "a": "En la nube las instancias suben/bajan con IPs dinámicas: hay que localizarlas en runtime.\nClient-side: el cliente consulta un registro (Eureka, Consul) y balancea él.\nServer-side: Service + DNS de Kubernetes o un LB ocultan las instancias.\nEn K8s nativo no necesitas Eureka: el DNS del Service resuelve.",
   "sub": "Comunicación",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "Patrones de resiliencia: timeout, retry, circuit breaker, bulkhead",
   "a": "Timeout: nunca esperes infinito.\nRetry: backoff exponencial + jitter, solo fallos transitorios y siendo idempotente.\nCircuit breaker: corta llamadas a un servicio caído y responde con fallback.\nBulkhead: aísla pools de hilos/conexiones por dependencia para que un fallo no hunda todo.\nResilience4j los implementa.",
   "sub": "Resiliencia",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "Patrón Saga (transacciones distribuidas)",
   "a": "Transacción que cruza servicios = secuencia de transacciones LOCALES; si un paso falla, se ejecutan acciones COMPENSATORIAS que deshacen los anteriores.\nCoreografía: cada servicio reacciona a eventos, sin coordinador.\nOrquestación: un orquestador central dirige los pasos.\nEvita el 2PC.",
   "sub": "Datos y consistencia",
   "nivel": "avanzado",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "¿Qué es CQRS?",
   "a": "Command Query Responsibility Segregation: separar el modelo de ESCRITURA (comandos, invariantes, normalizado) del de LECTURA (queries, denormalizado, optimizado para buscar).\nSe sincronizan por eventos.\nÚtil con cargas asimétricas o vistas complejas; añade duplicación y eventualidad.",
   "sub": "Datos y consistencia",
   "nivel": "avanzado",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "¿Qué es Event Sourcing?",
   "a": "Guardar el estado como secuencia INMUTABLE de eventos (no el estado actual): se reconstruye con replay.\nDa auditoría completa, time travel y encaja con CQRS.\nCostos: versionado de eventos, snapshots por rendimiento, complejidad.\nEj.: cuenta bancaria = lista de movimientos.",
   "sub": "Datos y consistencia",
   "nivel": "avanzado",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "Database per service",
   "a": "Cada microservicio es DUEÑO de su esquema/BD; nadie más lo consulta directo.\nBeneficio: acoplamiento cero, tecnología propia, escalado independiente.\nConsecuencia: no hay joins entre servicios → compartir por APIs o eventos; consultas cruzadas con API composition o CQRS.",
   "sub": "Datos y consistencia",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "Consistencia eventual",
   "a": "Con mensajería asíncrona y réplicas, los datos convergen con el tiempo: un usuario puede leer datos ligeramente viejos.\nSe diseña con: lectura de tu propia escritura, versiones/ETags, compensación en UI, procesos idempotentes.\nSi el negocio exige fuerte → transacción local o BD distribuida consistente (Spanner).",
   "sub": "Datos y consistencia",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "Idempotencia: ¿por qué es clave en microservicios?",
   "a": "Con reintentos y entrega at-least-once, la misma petición/mensaje puede procesarse 2+ veces.\nIdempotente = aplicarlo N veces da el mismo resultado que una vez.\nTécnicas: clave de idempotencia (header Idempotency-Key), upsert/MERGE, constraints únicos, deduplicación de IDs de mensaje.",
   "sub": "Datos y consistencia",
   "nivel": "avanzado",
   "clave": false
  },
  {
   "cat": "micro",
   "q": "Configuración centralizada en microservicios",
   "a": "Config externalizada por entorno, fuera del jar: Spring Cloud Config (backend Git), Consul, o K8s ConfigMaps/Secrets.\nBeneficios: un solo lugar para cambiar, refresco sin redeploy (@RefreshScope), historial y rollback.\nSecretos NUNCA en el repo: Secret Manager / Vault.",
   "sub": "Plataforma y despliegue",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "cat": "micro",
   "q": "Los 3 pilares de la observabilidad",
   "a": "LOGS (qué pasó, con contexto): centralizados (ELK, Cloud Logging) con correlation ID.\nMETRICS (números, tendencias): Micrometer → Prometheus/Grafana; RED (rate, errors, duration) por servicio.\nTRACING (recorrido entre servicios): OpenTelemetry → Jaeger/Tempo.\nLas tres juntas: con solo logs no ves el sistema.",
   "sub": "Observabilidad",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "Distributed tracing: ¿cómo funciona?",
   "a": "Cada petición lleva un traceId propagado en headers (W3C traceparent) por todos los saltos; cada servicio crea SPANS con timings enlazados al mismo trace.\nResultado: waterfall de toda la cadena con latencia por servicio.\nOpenTelemetry es el estándar (instrumentación + SDK).",
   "sub": "Observabilidad",
   "nivel": "intermedio",
   "clave": false
  },
  {
   "cat": "micro",
   "q": "Health checks: liveness vs readiness",
   "a": "Liveness: ¿el proceso vive? Si falla, K8s lo REINICIA.\nReadiness: ¿puedo atender tráfico? Si falla, me quitan del load balancer sin reiniciar.\nSpring Boot Actuator: /actuator/health/liveness y /readiness.\nNunca hagas que liveness dependa de una BD caída (reiniciaría en bucle).",
   "sub": "Plataforma y despliegue",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "Blue/green vs canary deployment",
   "a": "Blue/green: dos entornos idénticos; el router cambia de blue a green de golpe; rollback instantáneo.\nCanary: el release nuevo recibe un % creciente de tráfico (1% → 10% → 50% → 100%) mientras vigilas métricas; limita el impacto.\nK8s + Istio/Gateway API lo automatizan.",
   "sub": "Plataforma y despliegue",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "Los 12 factores (12-factor app)",
   "a": "Manifiesto cloud-native:\n1 base de código por servicio · 2 dependencias explícitas · 3 config en variables de entorno · 4 backends como recursos adjuntos · 5 build/release/run separados · 6 procesos stateless · 7 port binding · 8 concurrencia por procesos · 9 descartabilidad · 10 paridad dev/prod · 11 logs como stream · 12 tareas admin como procesos.",
   "sub": "Fundamentos y decisiones",
   "nivel": "intermedio",
   "clave": true
  },
  {
   "cat": "micro",
   "q": "Versionado de APIs sin romper clientes",
   "a": "Estrategias: en la URL (/api/v1/orders), por header (Accept versionado) o query param.\nReglas: no romper contratos (añadir campos sí; quitar/renombrar no), deprecar avisando, mantener versiones en paralelo, OpenAPI por versión, tests de contrato (Pact).",
   "sub": "APIs y edge",
   "nivel": "intermedio",
   "clave": true
  }
 ]
}