08 oct 2025·8 min de lectura

Numeración segura de facturas ante concurrencia: evitar duplicados y huecos

Aprende patrones prácticos para la numeración de facturas segura frente a concurrencia, para que varios usuarios puedan crear facturas o tickets sin duplicados ni huecos inesperados.

Numeración segura de facturas ante concurrencia: evitar duplicados y huecos

Qué falla cuando dos personas crean registros a la vez

Imagínate una oficina concurrida a las 16:55. Dos personas terminan una factura y pulsan Guardar con un segundo de diferencia. Ambos pantallas muestran brevemente “Factura #1042”. Un registro gana, el otro falla, o peor, ambos quedan almacenados con el mismo número. Ese es el síntoma más común en el mundo real: números duplicados que aparecen solo bajo carga.

Los tickets se comportan igual. Dos agentes crean un nuevo ticket para el mismo cliente al mismo tiempo, y tu sistema intenta “tomar el siguiente número” mirando el registro más reciente. Si ambas solicitudes leen el mismo valor “más reciente” antes de que alguna escriba, pueden elegir el mismo siguiente número.

El segundo síntoma es más sutil: números saltados. Puedes ver #1042, luego #1044, faltando el #1043. Esto suele ocurrir tras un error o un reintento. Una solicitud reserva un número y luego el guardado falla por una validación, un timeout, o un usuario que cierra la pestaña. O un job en background reintenta después de un problema de red y toma un nuevo número aunque el primer intento ya consumió uno.

Para facturas, esto importa porque la numeración forma parte del rastro de auditoría. Los contables esperan que cada factura esté identificada de forma única, y los clientes pueden referirse a números de factura en pagos o correos de soporte. Para tickets, el número es el identificador que todos usan en conversaciones, informes y exportaciones. Los duplicados crean confusión. Los números faltantes pueden levantar preguntas en revisiones, aunque no haya habido nada deshonesto.

Aquí está la expectativa clave que conviene fijar desde el principio: no todos los métodos de numeración pueden ser a la vez seguros frente a concurrencia y sin huecos. La numeración segura frente a concurrencia (sin duplicados, incluso con muchos usuarios) es alcanzable y debería ser innegociable. La numeración sin huecos también es posible, pero requiere reglas adicionales y a menudo cambia cómo manejas borradores, fallos y cancelaciones.

Una buena forma de encuadrar el problema es preguntarte qué debe garantizar tu numeración:

  • Nunca debe repetirse (único, siempre)
  • Debe ser mayoritariamente creciente (deseable)
  • Nunca debe saltarse (solo si lo diseñas así)

Una vez que eliges la regla, la solución técnica se vuelve mucho más fácil de escoger.

Por qué ocurren duplicados y huecos

La mayoría de las apps siguen un patrón simple: un usuario pulsa Guardar, la app pide el siguiente número de factura o ticket, y luego inserta el nuevo registro con ese número. Parece seguro porque funciona perfectamente cuando solo una persona lo hace.

El problema aparece cuando dos guardados ocurren casi al mismo tiempo. Ambas peticiones pueden llegar al paso “obtener siguiente número” antes de que cualquiera termine la inserción. Si ambas lecturas ven el mismo valor “siguiente”, intentan escribir el mismo número. Eso es una condición de carrera: el resultado depende del orden temporal, no de la lógica.

Un cronograma típico es este:

  • Solicitud A lee siguiente número: 1042
  • Solicitud B lee siguiente número: 1042
  • Solicitud A inserta la factura 1042
  • Solicitud B inserta la factura 1042 (o falla si una restricción única lo bloquea)

Los duplicados ocurren cuando nada en la base de datos detiene la segunda inserción. Si solo compruebas “¿está tomado este número?” en el código de la app, aún puedes perder la carrera entre la comprobación y la inserción.

Los huecos son un problema distinto. Ocurren cuando tu sistema “reserva” un número, pero el registro nunca llega a ser una factura o un ticket comprometido. Causas comunes: pagos fallidos, errores de validación detectados tarde, timeouts, o un usuario que cierra la pestaña después de que se asignó el número. Incluso si la inserción falla y no se guarda nada, el número puede haberse consumido.

La concurrencia oculta empeora esto porque rara vez es solo “dos humanos pulsando Guardar”. También puedes tener:

  • Clientes API creando registros en paralelo
  • Importaciones que corren por lotes
  • Jobs en background generando facturas por la noche
  • Reintentos desde apps móviles con conexiones inestables

Así que las causas raíz son: (1) conflictos de timing cuando múltiples solicitudes leen el mismo valor de contador, y (2) números asignados antes de que estés seguro de que la transacción tendrá éxito. Cualquier plan para numeración segura frente a concurrencia debe decidir qué resultado toleras: no duplicados, sin huecos, o ambos, y bajo exactamente qué eventos (borradores, reintentos, cancelaciones).

Decide tu regla de numeración antes de elegir una solución

Antes de diseñar la numeración segura frente a concurrencia, escribe qué debe significar el número en tu negocio. El error más común es elegir un método técnico primero y luego descubrir que las reglas contables o legales esperan otra cosa.

Empieza separando dos objetivos que a menudo se confunden:

  • Único: ningún par de facturas o tickets comparte el mismo número.
  • Sin huecos: los números son únicos y además estrictamente consecutivos (sin faltar ninguno).

Muchos sistemas reales optan por “único” y aceptan huecos. Los huecos pueden deberse a razones normales: un usuario abre un borrador y lo abandona, un pago falla después de reservar el número, o un registro se crea y luego se anula. Para tickets, los huecos suelen no importar. Incluso para facturas, muchos equipos aceptan huecos si pueden explicarlos con un rastro de auditoría (anulado, cancelado, prueba, etc.). La numeración sin huecos es posible, pero obliga a reglas adicionales y suele añadir fricción.

A continuación, decide el ámbito del contador. Diferencias sutiles en la redacción cambian mucho el diseño:

  • ¿Una secuencia global para todo, o secuencias separadas por empresa/inquilino?
  • ¿Reset anual (2026-000123) o nunca resetear?
  • ¿Series diferentes para facturas, notas de crédito y tickets?
  • ¿Necesitas un formato legible por humanos (prefijos, separadores) o solo un número interno?

Un ejemplo concreto: un producto SaaS con varias empresas cliente podría requerir números de factura únicos por empresa y que reinicien por año, mientras que los tickets son únicos globalmente y nunca se reinician. Son dos contadores diferentes con reglas distintas, aunque la interfaz parezca similar.

Si realmente necesitas "sin huecos", sé explícito sobre qué eventos están permitidos después de asignar un número. Por ejemplo: ¿se puede eliminar una factura, o solo anularla? ¿Los usuarios pueden guardar borradores sin número y asignarlo solo al aprobar? Estas elecciones suelen importar más que la técnica de base de datos.

Escribe la regla en una breve especificación antes de construir:

  • ¿Qué tipos de registro usan la secuencia?
  • ¿Qué hace que un número se considere “usado” (borrador, enviado, pagado)?
  • ¿Cuál es el ámbito (global, por empresa, por año, por serie)?
  • ¿Cómo manejas anulaciones y correcciones?

En AppMaster, este tipo de regla pertenece junto al modelo de datos y al flujo de procesos de negocio, para que el equipo implemente el mismo comportamiento en API, web y móvil sin sorpresas.

Enfoques comunes y lo que garantiza cada uno

Cuando la gente habla de “numeración de facturas”, a menudo mezcla dos objetivos diferentes: (1) nunca generar el mismo número dos veces y (2) nunca tener huecos. La mayoría de los sistemas pueden garantizar fácilmente lo primero. Lo segundo es mucho más difícil, porque los huecos pueden aparecer cuando una transacción falla, un borrador se abandona o un registro se anula.

Enfoque 1: Secuencia de base de datos (unicidad rápida)

Una secuencia de PostgreSQL es la forma más simple de obtener números únicos y crecientes bajo carga. Escala bien porque la base de datos está diseñada para entregar valores de secuencia rápidamente, incluso con muchos usuarios creando registros a la vez.

Lo que obtienes: unicidad y orden (mayormente creciente). Lo que no obtienes: números sin huecos. Si una inserción falla después de asignarse un número, ese número queda “quemado” y verás un hueco.

Enfoque 2: Restricción única más reintentos (deja que la BD decida)

Aquí generas un número candidato (desde la lógica de la app), lo guardas y confías en una restricción UNIQUE para rechazar duplicados. Si hay un conflicto, reintentas con un número nuevo.

Funciona, pero tiende a volverse ruidoso bajo alta concurrencia. Puedes terminar con más reintentos, más transacciones fallidas y picos difíciles de depurar. Tampoco garantiza ausencia de huecos a menos que lo combines con reglas estrictas de reserva, lo que añade complejidad.

Enfoque 3: Fila contadora con bloqueo (apunta a no huecos)

Si realmente necesitas números sin huecos, el patrón habitual es una tabla dedicada de contadores (una fila por ámbito de numeración, p. ej. por año o por empresa). Bloqueas esa fila en una transacción, la incrementas y usas el valor nuevo.

Esto es lo más cercano a no huecos en un diseño normal de base de datos, pero tiene un coste: crea un “punto caliente” en el que todos los escritores deben esperar. También aumenta el riesgo operativo (transacciones largas, timeouts, deadlocks).

Enfoque 4: Servicio de reservación separado (solo para casos especiales)

Un “servicio de numeración” independiente puede centralizar reglas entre múltiples apps o bases de datos. Suele valer la pena solo cuando tienes varios sistemas emitiendo números y no puedes consolidar escrituras.

El intercambio es riesgo operativo: añades otro servicio que debe ser correcto, altamente disponible y consistente.

Aquí una forma práctica de pensar sobre garantías:

  • Secuencia: único, rápido, acepta huecos
  • Único + reintento: único, simple a baja carga, puede comportarse mal a alta carga
  • Fila contadora con bloqueo: puede ser sin huecos, más lenta bajo alta concurrencia
  • Servicio separado: flexible entre sistemas, mayor complejidad y riesgos

Si construyes esto en una herramienta low-code como AppMaster, las mismas opciones aplican: la base de datos es donde reside la corrección. La lógica de la app puede ayudar con reintentos y mensajes claros, pero la garantía final debe venir de restricciones y transacciones.

Paso a paso: prevenir duplicados con secuencias y restricciones únicas

Añade unicidad de la manera correcta
Modela tablas PostgreSQL y restricciones únicas visualmente, sin escribir migraciones a mano.
Comenzar a crear

Si tu objetivo principal es prevenir duplicados (no garantizar ausencia de huecos), el patrón más simple y fiable es: deja que la base de datos genere un ID interno, y aplica una restricción de unicidad en el número visible al cliente.

Empieza por separar ambos conceptos. Usa un valor generado por la base de datos (identity/sequence) como clave primaria para joins, ediciones y exportaciones. Mantén invoice_no o ticket_no como una columna separada que se muestra a las personas.

Una configuración práctica en PostgreSQL

Aquí tienes un enfoque común en PostgreSQL que mantiene la lógica de “siguiente número” dentro de la base de datos, donde la concurrencia se maneja correctamente.

-- Internal, never-shown primary key
create table invoices (
  id bigint generated always as identity primary key,
  invoice_no text not null,
  created_at timestamptz not null default now()
);

-- Business-facing uniqueness guarantee
create unique index invoices_invoice_no_uniq on invoices (invoice_no);

-- Sequence for the visible number
create sequence invoice_no_seq;

Ahora genera el número visible al insertar (no haciendo select max(invoice_no) + 1). Un patrón sencillo es formatear el valor de la secuencia dentro del INSERT:

insert into invoices (invoice_no)
values (
  'INV-' || lpad(nextval('invoice_no_seq')::text, 8, '0')
)
returning id, invoice_no;

Incluso si 50 usuarios pulsan “Crear factura” a la vez, cada inserción obtiene un valor de secuencia diferente y el índice único evita duplicados accidentales.

Qué hacer cuando hay una colisión

Con una secuencia simple, las colisiones son raras. Suele ocurrir cuando añades reglas extra como “reset por año”, “por tenant” o números editables por el usuario. Por eso la restricción única sigue siendo importante.

A nivel de aplicación, maneja un error de violación de unicidad con un bucle de reintentos pequeño. Manténlo simple y acotado:

  • Intenta la inserción
  • Si hay una violación de restricción única en invoice_no, vuelve a intentarlo
  • Para después de un número pequeño de intentos y muestra un error claro

Esto funciona bien porque los reintentos solo se activan cuando ocurre algo inusual, como dos rutas de código que producen el mismo formato.

Mantén la ventana de carrera pequeña

No calcules el número en la UI y no “reserves” números leyendo antes e insertando después. Généralo lo más cerca posible de la escritura en la base de datos.

Si usas AppMaster con PostgreSQL, puedes modelar id como una clave primaria identity en el Data Designer, añadir una restricción única para invoice_no y generar invoice_no durante el flujo de creación para que ocurra junto con el INSERT. Así la base de datos sigue siendo la fuente de la verdad y los problemas de concurrencia quedan donde PostgreSQL es más fuerte.

Paso a paso: construir un contador sin huecos con bloqueo de fila

Mantén la numeración en el servidor
Usa un Business Process para generar números en el momento de insertar, no en la UI.
Prueba AppMaster

Si realmente necesitas números sin huecos, puedes usar una tabla contadora transaccional y bloqueo de fila. La idea es simple: solo una transacción a la vez puede tomar el siguiente número para un ámbito dado, así los números se entregan en orden.

Primero, decide tu ámbito. Muchos equipos necesitan secuencias separadas por empresa, por año o por serie (como INV vs CRN). La tabla de contadores almacena el último número usado para cada ámbito.

Aquí tienes un patrón práctico para numeración segura usando bloqueos de fila en PostgreSQL:

  1. Crea una tabla, por ejemplo number_counters, con columnas como company_id, year, series, last_number, y una clave única en (company_id, year, series).
  2. Inicia una transacción de base de datos.
  3. Bloquea la fila del contador para tu ámbito usando SELECT last_number FROM number_counters WHERE ... FOR UPDATE.
  4. Calcula next_number = last_number + 1, actualiza la fila del contador a last_number = next_number.
  5. Inserta la fila de la factura o ticket usando next_number, y luego haz commit.

La clave es FOR UPDATE. Bajo carga, no obtienes duplicados. Tampoco obtienes huecos por “dos usuarios obtuvieron el mismo número”, porque la segunda transacción no puede leer e incrementar la misma fila hasta que la primera haga commit (o haga rollback). En su lugar, la segunda petición espera brevemente. Esa espera es el precio de ser sin huecos.

Inicializar un ámbito nuevo

También necesitas un plan para la primera vez que aparece un ámbito (nueva empresa, nuevo año, nueva serie). Dos opciones comunes:

  • Precrear filas de contador por adelantado (por ejemplo, crear las filas del año siguiente en diciembre).
  • Crear bajo demanda: intenta insertar la fila del contador con last_number = 0, y si ya existe, cae de vuelta al flujo normal de bloqueo e incremento.

Si lo construyes en una herramienta no-code como AppMaster, mantén toda la secuencia “bloquear, incrementar, insertar” dentro de una transacción en tu lógica de negocio, para que ocurra todo o nada.

Casos límite: borradores, guardados fallidos, cancelaciones y ediciones

La mayoría de los errores de numeración aparecen en las partes desordenadas: borradores que nunca se publican, guardados que fallan, facturas anuladas y registros que se editan después de que alguien ya vio el número. Si quieres numeración segura frente a concurrencia, necesitas una regla clara sobre cuándo el número se considera “real”.

La decisión más importante es el momento de asignación. Si asignas un número en cuanto alguien pulsa “Nueva factura”, tendrás huecos por borradores abandonados. Si asignas solo cuando una factura se finaliza (publicada, emitida, enviada, o lo que “final” signifique en tu negocio), puedes mantener los números más ajustados y fáciles de explicar.

Los guardados fallidos y los rollbacks son donde las expectativas suelen chocar con el comportamiento de la base de datos. Con una secuencia típica, una vez que un número se toma, se toma aunque la transacción falle después. Eso es normal y seguro, pero puede crear huecos. Si tu política requiere números sin huecos, el número debe asignarse solo en el paso final y solo si la transacción hace commit. Eso suele significar bloquear una única fila contadora, escribir el número final y hacer commit como una unidad. Si cualquier paso falla, no se asigna nada.

Las cancelaciones y anulaciones casi nunca deben “reutilizar” un número. Conserva el número y cambia el estado. Los auditores y clientes esperan que la historia permanezca consistente aun cuando un documento se corrija.

Las ediciones son más sencillas: una vez que un número es visible fuera del sistema, trátalo como permanente. Nunca renumeres una factura o ticket después de que se haya compartido, exportado o impreso. Si necesitas corregir, crea un nuevo documento y referencia el anterior (por ejemplo, una nota de crédito o un ticket de reemplazo), pero no reescribas la historia.

Un conjunto de reglas práctico que muchos equipos adoptan:

  • Los borradores no tienen número final (usa un ID interno o “BORRADOR”).
  • Asigna el número solo en “Publicar/Emitir”, dentro de la misma transacción que cambia el estado.
  • Las anulaciones y cancelaciones mantienen el número, pero con estado y motivo claros.
  • Los números impresos/enviados nunca cambian.
  • Las importaciones preservan números originales y actualizan el contador al siguiente valor seguro.

Migraciones e importaciones merecen cuidado especial. Si migras desde otro sistema, trae los números de factura existentes tal cual y luego ajusta tu contador para empezar después del máximo importado. También decide qué hacer con formatos conflictivos (por ejemplo, prefijos por año). Suele ser mejor almacenar el “número visible” exactamente como estaba y mantener una clave primaria interna separada.

Ejemplo: un helpdesk crea tickets rápidamente, pero muchos son borradores. Asigna el número de ticket solo cuando el agente pulsa “Enviar al cliente”. Eso evita desperdiciar números en borradores abandonados y mantiene la secuencia visible alineada con la comunicación real al cliente. En una herramienta no-code como AppMaster, la misma idea aplica: mantén los borradores sin número público y genera el número final durante el paso de “enviar” que realiza el commit.

Errores comunes que causan duplicados o huecos inesperados

Envía un sistema de tickets escalable
Prototipa un helpdesk donde los números de ticket permanecen únicos en web, móvil y API.
Comenzar

La mayoría de los problemas de numeración nacen de una idea simple: tratar un número como un valor de presentación en lugar de estado compartido. Cuando varias personas guardan a la vez, el sistema necesita un sitio claro para decidir el siguiente número y una regla clara sobre qué pasa en caso de fallo.

Un error clásico es usar SELECT MAX(number) + 1 en el código de la aplicación. Parece bien en pruebas de un solo usuario, pero dos solicitudes pueden leer el mismo MAX antes de que cualquiera haga commit. Ambas generan el mismo siguiente valor y obtienes un duplicado. Incluso si añades un “comprueba y luego reintenta”, puedes crear carga extra y picos extraños bajo tráfico máximo.

Otra fuente común de duplicados es generar el número en el cliente (navegador o móvil) antes de guardar. El cliente no sabe lo que hacen otros usuarios y no puede reservar un número de forma segura si el guardado falla. Los números generados en el cliente están bien para etiquetas temporales como “Borrador 12”, pero no para IDs oficiales de factura o ticket.

Los huecos sorprenden a equipos que suponen que las secuencias son sin huecos. En PostgreSQL, las secuencias están diseñadas para unicidad, no para continuidad perfecta. Los números pueden saltarse cuando una transacción hace rollback, cuando prefetches de IDs ocurren o cuando la base de datos se reinicia. Esto es comportamiento normal. Si tu requisito real es “no duplicados”, una secuencia más restricción única suele ser la respuesta. Si necesitas realmente “sin huecos”, necesitas otro patrón (normalmente bloqueo de fila) y aceptarás concesiones en rendimiento.

El bloqueo también puede fallar si es demasiado amplio. Un bloqueo global para toda la numeración obliga a toda creación a hacer fila, aunque podrías particionar contadores por empresa, ubicación o tipo de documento. Eso puede ralentizar el sistema y hacer que los usuarios sientan que el guardado “está atascado al azar”.

Comprueba estos errores comunes al implementar numeración segura frente a concurrencia:

  • Usar MAX + 1 (o “buscar último número”) sin una restricción única a nivel de BD.
  • Generar números finales en el cliente y luego intentar “arreglar conflictos” más tarde.
  • Esperar que las secuencias de PostgreSQL sean sin huecos y tratar los huecos como errores.
  • Bloquear un contador compartido para todo, en lugar de particionar donde tenga sentido.
  • Probar solo con un usuario, de modo que las condiciones de carrera no aparezcan hasta el lanzamiento.

Consejo práctico de pruebas: ejecuta una prueba de concurrencia que cree de 100 a 1.000 registros en paralelo y luego comprueba duplicados y huecos inesperados. Si construyes en una herramienta no-code como AppMaster, la misma regla aplica: asegúrate de que el número final se asigne dentro de una única transacción del lado servidor, no en el flujo de la UI.

Comprobaciones rápidas antes de lanzar

Despliega donde tu equipo lo necesite
Construye apps completas y despliega en AppMaster Cloud o en tu propio AWS, Azure o GCP.
Prueba AppMaster

Antes de desplegar la numeración de facturas o tickets, repasa las partes que suelen fallar bajo tráfico real. El objetivo es simple: cada registro recibe exactamente un número de negocio y tus reglas se mantienen aunque 50 personas pulsen “Crear” a la vez.

Checklist práctica antes del lanzamiento:

  • Confirma que el campo de número comercial tiene una restricción única en la base de datos (no solo una comprobación en la UI). Esta es tu última línea de defensa si dos solicitudes chocan.
  • Asegúrate de que el número se asigna dentro de la misma transacción que guarda el registro. Si la asignación y el guardado están separados en solicitudes, acabarás viendo duplicados.
  • Si requieres números sin huecos, asigna el número solo cuando el registro esté finalizado (por ejemplo, al emitir la factura, no al crear el borrador). Los borradores, pagos fallidos y formularios abandonados son la fuente más común de huecos.
  • Añade una estrategia de reintentos para conflictos raros. Incluso con bloqueo de filas o secuencias, puedes topar con errores de serialización, deadlocks o violaciones únicas en casos límite. Un reintento simple con un pequeño backoff suele bastar.
  • Realiza pruebas de estrés con 20 a 100 creaciones simultáneas desde todos los puntos de entrada: UI, API pública e importaciones masivas. Prueba mezclas realistas como ráfagas, redes lentas y envíos dobles.

Una forma rápida de validar tu configuración es simular un momento de mucha actividad en el helpdesk: dos agentes abren el formulario “Nuevo ticket”, uno envía desde la web mientras un job de importación inserta tickets desde el buzón de correo al mismo tiempo. Tras la ejecución, comprueba que todos los números son únicos, tienen el formato correcto y que los fallos no dejan registros a medio guardar.

Si construyes el flujo en AppMaster, los mismos principios aplican: asigna números en la transacción de base de datos, confía en las restricciones de PostgreSQL y prueba acciones de UI y endpoints API que creen la misma entidad. Muchos equipos se sienten seguros en pruebas manuales pero se sorprenden el primer día que entran usuarios reales.

Ejemplo: tickets de helpdesk ocupados y qué hacer a continuación

Imagina un soporte donde los agentes crean tickets todo el día en la web, mientras una integración también crea tickets desde chat y correo. Todos esperan números como T-2026-000123 y que cada número apunte exactamente a un ticket.

Un enfoque ingenuo es: leer “último número de ticket”, sumar 1 y guardar el ticket. Bajo carga, dos solicitudes pueden leer el mismo “último número” antes de que cualquiera guarde. Ambas calculan el mismo siguiente número y obtienes duplicados. Si intentas “arreglarlo” reintentando tras un fallo, a menudo generas huecos sin querer.

La base de datos puede evitar duplicados incluso si tu código de app es ingenuo. Añade una restricción única en la columna ticket_number. Entonces, cuando dos inserciones intentan el mismo número, una falla y puedes reintentar con limpieza. Esto es el núcleo de la numeración segura de facturas: deja que la base de datos haga cumplir la unicidad, no la UI.

La numeración sin huecos cambia el flujo. Si requieres no huecos, normalmente no puedes asignar el número final al crear el ticket (borrador). En su lugar, crea el ticket con estado Draft y sin ticket_number. Asigna el número solo cuando el ticket se finalice, de modo que fallos y borradores abandonados no “quemen” números.

Un diseño simple de tablas podría ser:

  • tickets: id, created_at, status (Draft, Open, Closed), ticket_number (nullable), finalized_at
  • ticket_counters: key (por ejemplo "tickets_2026"), next_number

En AppMaster puedes modelar esto en el Data Designer con tipos PostgreSQL y luego construir la lógica en el Business Process Editor:

  • Crear Ticket: insertar ticket con status=Draft y sin ticket_number
  • Finalizar Ticket: iniciar una transacción, bloquear la fila del contador, asignar ticket_number, incrementar next_number, hacer commit
  • Prueba: ejecutar dos acciones “Finalizar” al mismo tiempo y confirmar que nunca hay duplicados

Qué hacer después: empieza definiendo tu regla (solo único vs realmente sin huecos). Si puedes aceptar huecos, una secuencia de base de datos más una restricción única suele bastar y mantiene el flujo simple. Si necesitas sin huecos, mueve la numeración al paso de finalización y trata “borrador” como un estado de primera clase. Luego haz pruebas de carga con varios agentes y con integraciones API para ver el comportamiento antes de que ocurran con usuarios reales.

Fácil de empezar
Crea algo sorprendente

Experimente con AppMaster con plan gratuito.
Cuando esté listo, puede elegir la suscripción adecuada.

Empieza
Numeración segura de facturas ante concurrencia: evitar duplicados y huecos | AppMaster