Logo
Nuevos usuarios de RPC: 35% de descuento el primer mesVer oferta
OnFinality Learn
Guías de red y protocolo13 min de lectura

Niveles de commitment de Solana: processed vs confirmed vs finalized

Cómo los niveles de commitment processed, confirmed y finalized de Solana cambian lo que devuelve cada lectura RPC, y cómo elegir uno deliberadamente.

TL;DR

El parámetro commitment de Solana indica a un nodo RPC qué tan avanzado debe estar un slot en el proceso de elección de bifurcación y votación antes de responder a tu lectura. processed significa que el nodo ha producido o visto el bloque localmente y aún puede revertirse; confirmed significa que una supermayoría del stake ha votado por él; finalized significa que el bloque está enraizado y no puede revertirse sin reiniciar el clúster. El commitment es un argumento por llamada, por lo que la misma dirección o firma puede devolver resultados diferentes en distintos niveles, especialmente en torno a bifurcaciones. Elige confirmed para la experiencia de usuario, finalized para liquidación y contabilidad, y processed solo para lecturas especulativas sensibles a la latencia.

Qué controla realmente el parámetro commitment

Todos los métodos de lectura JSON-RPC de Solana aceptan un objeto commitment opcional, por ejemplo {"commitment":"confirmed"}. No es una configuración global del nodo ni una propiedad de una dirección o transacción: es una instrucción por llamada que le dice al nodo el nivel mínimo de irreversibilidad que estás dispuesto a aceptar antes de que responda. La misma llamada getBalance en processed y en finalized puede devolver legítimamente valores de lamports diferentes.

La documentación oficial de RPC de Solana define los tres niveles y sus valores predeterminados, y la documentación de confirmación y expiración de transacciones describe cómo un bloque pasa de producido a enraizado. Considera esas dos páginas como las fuentes primarias autorizadas; todo lo que sigue explica el mecanismo y cómo aplicarlo sobre RPC.

Como el commitment es por llamada, un bot de trading, un indexador o una dApp pueden leer los mismos datos en dos niveles en el mismo segundo y obtener dos respuestas diferentes, individualmente correctas. La habilidad está en decidir qué nivel merece cada lectura en lugar de copiar un valor predeterminado.

  • processed: el nodo ha producido u observado el bloque localmente; aún puede revertirse.
  • confirmed: una supermayoría del stake ha votado por el bloque; lo usan la mayoría de las interfaces y es el predeterminado para muchas lecturas.
  • finalized: el bloque está enraizado; no puede revertirse sin reiniciar el clúster.

El flujo de slots, los votos y el enraizamiento entre los niveles

Solana produce un flujo continuo de slots mediante proof-of-history, con un líder programado para cada slot. Un bloque en un slot no es irreversible al instante; se vuelve progresivamente más irreversible a medida que los validadores votan. Un voto es la atestación firmada de un validador de que ha visto y acepta un bloque en un slot y altura determinados.

Cuando una supermayoría de validadores con stake ha votado por un bloque, este alcanza el umbral confirmed. A medida que se acumulan votos sobre ese bloque y sus descendientes, el clúster enraiza el bloque, que es el estado finalized. El enraizamiento es lo que hace que una reversión requiera reiniciar el clúster en lugar de una elección de bifurcación ordinaria.

Por eso los niveles son una escalera, no tres estados no relacionados. processed es la vista local del nodo, confirmed es la vista del clúster ponderada por stake, y finalized es el historial enraizado. Una lectura en un nivel superior responde a una pregunta más estricta sobre la misma cadena.

La escalera de commitment y su mecánica de votos/root están documentadas por Solana en Transaction Confirmation & Expiration; esa página es la fuente primaria autorizada para los niveles descritos a continuación.

Por qué la misma lectura puede diferir entre niveles de commitment

Durante una bifurcación, una transacción o un bloque puede existir en processed en un nodo y estar ausente en finalized porque la bifurcación en la que vivía no se enraizó. Una lectura de saldo en processed puede incluir una transferencia que una lectura finalized aún no refleja, o puede reflejar una transferencia que luego desaparece con la bifurcación.

Esta es la consecuencia central para indexadores y sistemas contables: una lectura processed exitosa no es final. Si cuentas depósitos en processed, puedes duplicar el conteo o contar una transferencia que nunca se enraiza. Si liquidas en confirmed, aceptas un pequeño riesgo residual de reorganización que finalized elimina.

La regla práctica es hacer coincidir el commitment con el costo de equivocarse. El estado especulativo de la interfaz puede tolerar processed; el movimiento de dinero y los asientos contables no deberían.

getLatestBlockhash, expiración y el bucle de reintentos

getLatestBlockhash requiere un commitment porque el blockhash que devuelve solo es válido durante una ventana acotada, comúnmente descrita como de unos 150 bloques. Si obtienes el blockhash en processed y luego esperas, el hash puede expirar antes de que aterrice tu transacción, produciendo un error de expiración en lugar de un problema de bifurcación.

Obtén el blockhash en el mismo nivel en el que pretendes confirmar, o al menos en confirmed, y vuelve a obtenerlo cuando reconstruyas una transacción tras un timeout. Esto interactúa directamente con la estrategia de reintentos: un reintento que reutiliza un blockhash expirado fallará sin importar cuántas veces lo envíes. Consulta Tiempos de espera, reintentos y envío de transacciones en Solana RPC para la mecánica de envío y reintento que lo rodea.

Un emisor robusto obtiene un blockhash nuevo, firma, envía, luego sondea el estado en un commitment elegido y reconstruye con un nuevo blockhash si la ventana se cierra.

Leer el commitment desde cada superficie RPC principal

getBalance, getAccountInfo y getTransaction aceptan un commitment y responden en ese nivel. getSignatureStatuses es la forma correcta de sondear una transacción que has enviado, porque devuelve un campo confirmationStatus por firma que te dice si el clúster actualmente la ve como processed, confirmed o finalized.

Las suscripciones WebSocket fijan el nivel de notificación en el momento de suscribirse. No puedes cambiar el commitment en una suscripción existente; debes cancelar la suscripción y volver a suscribirte. La guía Pubsub y suscripciones WebSocket de Solana RPC cubre el ciclo de vida de las suscripciones en detalle.

Para lecturas históricas, el commitment sigue aplicándose pero los datos ya están enraizados, por lo que el nivel afecta principalmente cómo el nodo sirve la consulta en lugar de si la respuesta puede cambiar. Consulta Consultar datos históricos de Solana vía RPC para esa distinción.

  • getLatestBlockhash: el commitment controla qué blockhash recibes y qué tan reciente es.
  • getBalance / getAccountInfo: el commitment controla si se incluye estado no enraizado.
  • getTransaction: el commitment controla si se devuelve una transacción en una bifurcación no enraizada.
  • getSignatureStatuses: expone confirmationStatus, la superficie de sondeo correcta para transacciones enviadas.
  • Suscripciones WebSocket: el nivel de notificación se fija al suscribirse.

Enviar en un nivel y confirmar en otro

Enviar una transacción no conlleva un commitment de la misma manera que una lectura; la transacción se difunde y el clúster decide. Lo que controlas es el commitment que usas cuando sondeas su estado. Un patrón de producción común es enviar, luego sondear getSignatureStatuses en confirmed para la experiencia de usuario, y exigir por separado finalized antes de acreditar una cuenta.

Mezclar niveles sin cuidado es un error frecuente: un bot envía, sondea en processed, ve éxito y actúa sobre una transacción que luego desaparece con una bifurcación. La solución no es evitar processed por completo, sino hacer explícita la puerta de confirmación y consistente con el riesgo de la acción.

Si necesitas migrar desde métodos de confirmación más antiguos, Migrar desde métodos RPC obsoletos de Solana explica los reemplazos de getConfirmed* y cómo encaja el commitment en la superficie más nueva.

Ejemplo ejecutable: obtención de blockhash más una escalera de commitment

El script a continuación obtiene un blockhash en confirmed, no envía nada y demuestra el sondeo de getSignatureStatuses con una escalera de commitment. Reemplaza la firma por una que hayas enviado realmente. Usa solo JSON-RPC estándar sobre HTTPS, por lo que funciona contra cualquier endpoint RPC de Solana que configures.

Ejecútalo contra tu propio endpoint y registra las transiciones observadas de confirmationStatus y el tiempo transcurrido. No trates ninguna ejecución individual como un benchmark; el objetivo es ver la escalera moverse de processed a confirmed a finalized para tu propio tráfico.

// Node.js 18+ (global fetch). Set RPC_URL to your endpoint.
const RPC_URL = process.env.RPC_URL || "https://api.mainnet-beta.solana.com";

async function rpc(method, params) {
  const res = await fetch(RPC_URL, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
  });
  const json = await res.json();
  if (json.error) throw new Error(JSON.stringify(json.error));
  return json.result;
}

async function main() {
  // 1. Fresh blockhash at confirmed. Re-fetch if the window closes.
  const bh = await rpc("getLatestBlockhash", [{ commitment: "confirmed" }]);
  console.log("blockhash:", bh.value.blockhash, "lastValidBlockHeight:", bh.value.lastValidBlockHeight);

  // 2. Poll a signature you have sent. Replace with a real signature.
  const signature = process.env.SIGNATURE;
  if (!signature) {
    console.log("Set SIGNATURE to poll a real transaction.");
    return;
  }

  const ladder = ["processed", "confirmed", "finalized"];
  const start = Date.now();
  for (const commitment of ladder) {
    const status = await rpc("getSignatureStatuses", [[signature], { commitment }]);
    const v = status.value[0];
    console.log(
      commitment.padEnd(10),
      "confirmationStatus:", v ? v.confirmationStatus : "null",
      "slot:", v ? v.slot : "-",
      "err:", v ? JSON.stringify(v.err) : "-",
      "t+", Date.now() - start, "ms"
    );
  }
}

main().catch((e) => { console.error(e); process.exit(1); });

Tabla de resultados: mide contra tu propio endpoint

El comportamiento del proveedor, la topología del nodo y las condiciones de red varían, por lo que los únicos números confiables son los que mides tú. Completa la tabla a continuación con ejecuciones repetidas del script anterior contra tu propio endpoint, y conserva el tamaño de muestra y la ventana temporal junto con los resultados.

Registra el confirmationStatus que observaste en cada commitment, el tiempo transcurrido desde el envío hasta cada nivel, y cualquier respuesta nula o de error. Un estado nulo en finalized para una transacción que viste en processed es una señal de bifurcación o expiración que vale la pena investigar, no un error del script.

  • Columnas a completar: nivel de commitment | confirmationStatus observado | ms transcurridos | slot | err | notas.
  • Ejecuta al menos 20 envíos en diferentes momentos del día antes de sacar conclusiones.
  • Conserva el endpoint, la región y la versión del cliente junto a la tabla para que los resultados sigan siendo comparables.
  • Documentado / varía según el proveedor: los tiempos absolutos de confirmación y las latencias de estado no son constantes fijas.

Tabla de decisión: hacer coincidir el commitment con el caso de uso

Usa esto como política inicial y luego ajústala con tus propias mediciones. El objetivo es una elección deliberada por llamada, no un único valor predeterminado global.

Para cualquier cosa que mueva dinero o escriba un asiento contable inmutable, finalized es la puerta segura. Para una interfaz interactiva que el usuario puede ver cambiar, confirmed es el equilibrio habitual. processed es para lecturas especulativas sensibles a la latencia donde una corrección posterior es aceptable.

  • Saldo o cartera en vivo en la interfaz: confirmed.
  • Acreditación de depósitos, retiros, asientos contables: finalized.
  • Vista previa especulativa de precio o estado, no vinculante: processed.
  • Sondear una transacción enviada para la experiencia de usuario: getSignatureStatuses en confirmed.
  • Liquidación o acción irreversible: getSignatureStatuses en finalized.
  • Analítica histórica sobre datos enraizados: finalized.

Solución de problemas comunes de commitment

La mayoría de los errores de commitment son desajustes, no fallos del protocolo. Si una transacción parece exitosa y luego desaparece, probablemente actuaste sobre una lectura processed. Si un depósito se acredita dos veces, puede que estés contando en processed y de nuevo en finalized sin deduplicación.

Si una transacción nunca se confirma, revisa la ventana del blockhash antes de culpar al clúster: un blockhash expirado falla independientemente del commitment. Si una notificación WebSocket nunca llega en el nivel que esperas, confirma que te suscribiste en ese nivel, porque no puede cambiarse en el lugar.

Si getTransaction devuelve null en finalized pero viste la transacción en processed, trátalo como un evento de bifurcación o expiración y concilia contra una fuente enraizada antes de reintentar.

  • Mezclar niveles entre envío y confirmación: estandariza la puerta de confirmación en un solo lugar.
  • Asumir que confirmed equivale a finalized: son umbrales diferentes con distinto riesgo de reversión.
  • Ignorar confirmationStatus: léelo explícitamente en lugar de inferirlo de un resultado nulo o no nulo.
  • Leer saldos en processed y duplicar el conteo: deduplica por firma y liquida en finalized.
  • Tratar una transacción confirmed como irreversible para liquidación: exige finalized para el movimiento de dinero.

Limitaciones, compensaciones y cuándo revisar

Un commitment más alto cuesta latencia y puede devolver null para datos que existen pero aún no están enraizados. Un commitment más bajo es más rápido pero te expone a reversiones. No hay una configuración que sea a la vez máximamente rápida y máximamente segura; la compensación es el propósito del parámetro.

Este artículo describe el comportamiento documentado del protocolo y de RPC, no el rendimiento específico de OnFinality. Los tiempos absolutos de confirmación, las latencias de estado y el comportamiento de límite de tasa están documentados / varían según el proveedor y deben medirse en tu propio endpoint. Para opciones de endpoint y cómo compararlas, consulta Endpoints RPC de Solana (RPC Assistant) y Precios de RPC.

Revisa tu política cuando cambie el comportamiento de voto del clúster, la topología de tu proveedor o la tolerancia al riesgo de tu aplicación. Si estás levantando infraestructura nueva, comienza por Redes de Solana y el centro de aprendizaje de OnFinality.

Próximos pasos: operacionaliza tu política de commitment

Escribe tu política de commitment como una tabla similar a la anterior, luego aplícala en el código para que ningún sitio de llamada use un valor predeterminado silencioso. Centraliza la puerta de confirmación, registra las transiciones de confirmationStatus y alerta cuando una lectura finalized no coincida con una lectura processed anterior.

Mide tu propio endpoint con la tabla de resultados, conserva el tamaño de muestra junto con los números y vuelve a ejecutar tras cualquier cambio de proveedor o topología. Si estás evaluando acceso gestionado, revisa las páginas de Servicio de API y Endpoints RPC de Solana (RPC Assistant), y combina esta guía con Tiempos de espera, reintentos y envío de transacciones en Solana RPC para que el manejo de expiración y reintentos coincida con tus elecciones de commitment.

Nunca te preocupes por la infraestructura nuevamente

OnFinality elimina la carga pesada de DevOps para que puedas construir de forma más inteligente y rápida.

Comenzar