Guías de ingeniería
Cómo crear un importador de CSV para una aplicación SaaS
Una guía de ingeniería sobre análisis, mapeo, autoridad sobre el tenant, validación, escrituras, reintentos y conciliación, con una vía clara para las importaciones más sencillas.
Crea el flujo más sencillo que permita al usuario revisar una propuesta de importación y a tu backend dar cuenta de cada registro aceptado. Para una función reutilizable, esto suele implicar una recepción de archivos con límites, análisis, un mapeo de columnas aprobado, validación y corrección, un plan de escritura confirmado y un resultado persistente. El componente que escribe en el destino debe aplicar la autorización y el comportamiento de los reintentos de forma independiente del navegador.
Para un solo archivo conocido, puede bastar con un script revisado o con el editor de tablas de Supabase. No necesitas crear un producto de importación para migrar los datos de un único cliente. Esta guía muestra en qué casos se justifica la complejidad de una función reutilizable y plantea decisiones concretas que un ingeniero debe tomar en cada punto de separación de responsabilidades.
Alcance y supuestos. Orientaciones de arquitectura para importar datos de clientes en PostgreSQL/Supabase. La semántica SQL corresponde a PostgreSQL 17. El pseudocódigo describe un diseño, no un SDK de ImportFlow.
Decide si necesitas una función reutilizable
| Necesidad | Empieza por | Motivo para ampliar |
|---|---|---|
| Un conjunto de datos interno, un esquema estable y un operador técnico | La importación de CSV integrada o un pequeño script revisado | Los requisitos de repetibilidad o auditoría superan lo que ofrece el script |
| Una migración de datos de un cliente con distintos significados en los campos | Mapeo explícito, ensayo aislado y ejecución revisada | Las mismas decisiones se repiten entre clientes |
| Los clientes cargan archivos sin que haya un ingeniero presente | Un flujo de importación con correcciones y resultados persistentes | El equipo de soporte debe resolver fallos sin reproducir una sesión del navegador |
Una herramienta de carga interna puede contar con un operador formado y un formato de archivo controlado. La incorporación de clientes normalmente no puede hacerlo. Un cliente puede no saber qué hoja es la fuente válida, por qué se rechazó un valor de enum o qué registros existen ya. La interfaz debe hacer visibles esas decisiones sin exigir al cliente que entienda tu esquema.
Los analizadores existentes y las interfaces de importación de código abierto pueden ahorrarte trabajo. Evalúa su comportamiento con tus casos reales de archivos y revisa dónde vuelve a recaer la responsabilidad en tu aplicación. Un callback que entrega filas validadas es un componente útil; no define la transacción de tu base de datos, la autoridad sobre el tenant ni el procedimiento de recuperación.
Si la tarea inmediata es una importación administrativa en Supabase, usa primero el tutorial de importación con las herramientas integradas.
Empieza con un contrato de importación por escrito
Define qué representa una fila y si la operación inserta, actualiza o hace un upsert. Son contratos distintos. Para las actualizaciones, la correspondencia de identidades y los cambios permitidos necesitan su propia aprobación. Evita un upsert genérico solo porque haga desaparecer los errores de duplicados.
Un contrato breve para contactos podría indicar lo siguiente:
Operation: insert new contacts
Target: one approved application table
Source fields: external_contact_ref, email, display_name
Tenant: supplied by an authorized import job
Primary key: generated by the database
External identity: unique within tenant + source system
Missing display name: NULL
Existing external identity: report conflict; do not overwrite
Accepted set: frozen after review; edits require revalidationAnota también los formatos y límites de archivo admitidos, las reglas de transformación, la versión del esquema, la política de errores y las pruebas necesarias para dar la tarea por completada. Es un documento de ingeniería. No necesita un lenguaje de configuración ni un compilador.
Una versión vincula la vista previa con el comportamiento que se ejecutará. Si cambia un mapeo o una regla de normalización después de la confirmación, invalida la vista previa anterior. Si cambia el esquema de destino, vuelve a evaluar la compatibilidad en lugar de suponer que las columnas revisadas antes siguen teniendo el mismo significado.
Establece límites para los archivos y su análisis
Elige dónde se analiza el archivo. Analizarlo en el navegador puede mantener un archivo exploratorio en local y ofrecer vistas previas ágiles. Analizarlo en el servidor permite ejecutar trabajos que continúen al cerrar la pestaña. Ambos métodos necesitan límites de recursos; antes de escribir, el sistema debe repetir la validación del navegador desde un entorno de confianza.
Establece límites de bytes, registros, columnas, longitud de las celdas, tiempo de procesamiento y detalles de errores conservados. En XLSX, el tamaño del archivo comprimido por sí solo no limita el tamaño descomprimido ni el número de hojas o celdas. Procesa en streaming o delega el trabajo cuando corresponda, y detén el proceso con un mensaje útil cuando se superen los límites del archivo o del procesamiento.
Para las cargas, autentica el acceso, genera tu propia clave de almacenamiento y aísla los archivos por trabajo autorizado. No confíes en un nombre de archivo como ruta. Define expresamente la conservación de las cargas abandonadas, los trabajos completados, los trabajos fallidos y las copias de seguridad. Un archivo guardado «temporalmente» sin un mecanismo de eliminación se conserva indefinidamente en la práctica.
Admitir solo CSV es una primera versión válida. Si admites libros de cálculo, permite que el usuario elija la hoja y la fila de encabezados, documenta el comportamiento de las fórmulas y los valores en caché, y no ejecutes macros de hojas de cálculo ni enlaces externos. Indica al usuario qué se ha ignorado.
Conserva los valores durante el análisis
Usa un analizador con mantenimiento activo en vez de dividir el texto por comas o saltos de línea. RFC 4180 describe los delimitadores y saltos de línea entre comillas, pero las exportaciones reales siguen variando en codificación, delimitadores y tratamiento de valores en blanco. Admite un conjunto documentado de variantes y muestra la interpretación detectada antes de ejecutar la importación.
Conserva los identificadores como cadenas. La conversión numérica automática puede eliminar ceros iniciales o redondear un número de cuenta largo. Las opciones del analizador, como el tipado dinámico, la gestión de encabezados y los informes de errores de Papa Parse, se documentan en su referencia de la API; elígelas de forma deliberada.
| Caso de prueba | Comportamiento esperado que debes definir |
|---|---|
| Coma o salto de línea dentro de una celda entre comillas | Un campo / un registro, sin crear una columna o un registro adicional |
| BOM de UTF-8 y nombres con caracteres no ASCII | Encabezado reconocido y nombres conservados |
| Encabezado duplicado o dos encabezados mapeados al mismo campo | Conflicto explícito, sin sobrescritura silenciosa |
| 00042 y una referencia externa de 20 dígitos | Conservación exacta de la cadena |
| Celda vacía, celda vacía entre comillas y campo ausente | Semántica documentada, distinta o unificada de forma intencional |
| Fecha ambigua o decimal en formato local | Solicitar la interpretación, sin adivinarla |
| Comillas mal formadas o número inesperado de campos | Diagnóstico acotado con la ubicación en el origen |
Mantén un identificador de registro de origen a lo largo de las correcciones y escrituras. Los números de línea física ayudan a localizar errores de análisis, pero un registro multilínea entre comillas puede abarcar varias líneas. Un resultado debe permitir volver al registro de origen sin dar a entender que ambos conceptos son siempre intercambiables.
Permite mapear únicamente campos en los que se pueda escribir
Presenta los campos de destino que el origen tiene permiso para aportar. Las sugerencias pueden ahorrar escritura; no deben crear nuevos permisos de escritura. Exige que se resuelvan los campos obligatorios ausentes, los mapeos en conflicto y las columnas de origen excluidas.
Un encabezado de origen como «Owner» podría referirse a un comercial, un espacio de trabajo o el creador del registro antiguo. Muestra la descripción del destino y valores de ejemplo, además de la puntuación de similitud. Conserva el mapeo confirmado con el trabajo para que el equipo de soporte pueda explicar el resultado más adelante.
Vuelve a rechazar las claves desconocidas en el servidor. Construye las escrituras de la base de datos a partir de los campos de destino aprobados, nunca de claves arbitrarias de la solicitud. Parametriza los valores y usa una lista revisada de identificadores permitidos cuando no se puedan evitar los identificadores dinámicos. Un nombre de archivo o un encabezado no debe convertirse en SQL ejecutable.
Clasifica por separado los valores predeterminados, las identidades y las expresiones generadas. Un valor predeterminado ordinario no protege un campo. Consulta valores aportados por la base de datos durante la importación de CSV para ver un ejemplo ejecutable.
Separa la normalización de las decisiones de negocio
La normalización aplica una interpretación aprobada. Una decisión de negocio elige esa interpretación. Recortar espacios en un formato de identificador acordado puede ser mecánico; decidir que «antiguo cliente» corresponde a «inactivo» requiere autoridad sobre el dominio. Trata una zona horaria inferida, la sustitución de un enum o la elección del registro que prevalece entre duplicados como un cambio propuesto hasta que se apruebe.
Valida por capas y ofrece un error útil en el primer punto donde pueda determinarse de forma fiable:
- Estructura del archivo: codificación, registros, encabezados y límites admitidos.
- Valores de los campos: obligatoriedad, tipos, rangos y formatos aceptados.
- Relaciones dentro del archivo: duplicados y referencias repetidas incoherentes.
- Reglas de negocio: estados permitidos, semántica de identidad y permisos.
- Comprobaciones del destino: restricciones aplicables, existencia de referencias y comportamiento real de escritura.
Una consulta al destino refleja un hecho en un momento concreto. Otra transacción puede insertar el mismo valor único entre la vista previa y la ejecución. Mantén la restricción como autoridad final y gestiona su incumplimiento; una vista previa sin errores no reserva nada.
Los errores deben identificar el registro, el campo, la regla y una posible corrección sin registrar valores sensibles en los logs. Agrupa los problemas repetidos para que el usuario pueda corregir de una vez un problema sistemático. La decisión de excluir registros necesita un recuento y un motivo visibles; descartar filas silenciosamente provoca una discrepancia sin explicación más adelante.
Muestra el resultado propuesto antes de escribir
Una vista previa útil muestra los recuentos de registros aceptados y excluidos, las correcciones necesarias, las transformaciones aprobadas, el tenant de destino y la operación. Indica qué comprobaciones se realizaron contra un destino real y cuáles fueron estáticas o locales.
Si una pasada de validación no realiza escrituras, descríbela exactamente así. Una transacción que realiza escrituras reales y luego las revierte no es necesariamente una simulación sin efectos secundarios: la asignación de valores de secuencia y los efectos iniciados en sistemas externos pueden no revertirse. Ensaya el comportamiento de escritura en un entorno aislado diseñado para ello.
Vincula la confirmación al archivo, el mapeo, las reglas y el conjunto de registros aceptados. Editar una celda después de confirmar debe generar una propuesta validada de nuevo. Para entradas grandes, virtualiza la cuadrícula de corrección si es necesario y conserva el acceso por teclado, las etiquetas de los campos y un resumen fuera de las filas virtualizadas.
Resuelve la autoridad sobre el tenant y las claves foráneas
Vincula el trabajo a un tenant y un operador autorizados. Aporta los campos controlados por el tenant a través del componente de escritura de confianza. Un campo oculto del navegador sigue siendo una entrada controlada por el navegador. Si la RLS forma parte del diseño, prueba con el rol real de ejecución y el conjunto de políticas; el acceso con el rol de servicio cambia ese límite de autoridad.
Una referencia como «Empresa 42» suele identificar una fila del sistema antiguo. Resuelve una clave externa aprobada dentro del espacio de nombres correcto de tenant y origen. Cero coincidencias y varias coincidencias son fallos distintos; elegir la primera fila oculta la ambigüedad. Mantén activas las restricciones finales de clave foránea y de coherencia del tenant.
Las guías detalladas de autoridad sobre el tenant y resolución de claves foráneas muestran estos límites. El orden de carga entre varias tablas y los ciclos requieren un plan relacional explícito; no son funciones de mapeo de columnas.
Confirma las escrituras y su comprobante en una misma transacción
Para una importación pequeña y acotada, una sola transacción suele ser el modelo de resultados más sencillo. Para trabajos mayores, elige los lotes según mediciones de la duración de las transacciones, la memoria, los bloqueos y la carga de la base de datos. Copiar el tamaño de lote de un tutorial no equivale a planificar la capacidad.
Asigna una identidad estable a cada trabajo y lote. Un reintento idéntico debería devolver el mismo resultado registrado; debe rechazarse un contenido distinto que use la misma identidad. El comprobante y las escrituras en el destino deben confirmarse en la misma transacción para que el comprobante pueda demostrar esas escrituras.
BEGIN
authorize access to this job
lock the existing job row FOR UPDATE
look up receipt for (job_id, batch_number)
if receipt exists:
require matching payload hash and contract version
return recorded result without inserting again
else:
check job state and the next expected batch
validate and insert the approved rows
insert receipt with identity, hash and result
advance the job's committed progress
COMMITEsto es un esquema de diseño, no SQL ejecutable. El bloqueo de la fila del trabajo serializa los intentos que compiten por ese trabajo, y una clave única del comprobante aporta una restricción adicional en la base de datos. La autorización también se aplica al leer un comprobante existente. Define una representación estable para calcular el hash que incluya los valores aceptados y la identidad pertinente del contrato.
No guardes un comprobante en una base de datos y las escrituras de destino en otra para después afirmar que ambas operaciones son atómicas. Si debes cruzar sistemas, especifica un protocolo de conciliación para cubrir esa separación. Del mismo modo, una confirmación de recepción de una cola y un commit de la base de datos no constituyen una sola transacción por el mero hecho de ocurrir en la misma función.
Si deben enviarse notificaciones o webhooks después de un commit, una tabla outbox escrita dentro de la transacción puede registrar los envíos pendientes. El envío sigue necesitando sus propias reglas de idempotencia y reintento. Mantén el contenido de las filas importadas fuera de las cargas útiles habituales de los eventos.
Representa con honestidad los resultados parciales y desconocidos
Una respuesta perdida no demuestra que la transacción haya fallado. Consulta un comprobante persistente o reintenta el lote idéntico a través de la vía idempotente. Si no puedes acceder a esas pruebas, muestra un resultado sin resolver y detén los reintentos indiscriminados de toda la importación.
Si se confirmaron los lotes 1–4 y falló el lote 5, informa del subconjunto confirmado y del resto fallido o aún no intentado. Un botón de cancelación puede detener el trabajo futuro; no puede prometer deshacer los lotes confirmados. Una operación para deshacerlos necesitaría un cambio compensatorio revisado por separado, incluidos sus efectos sobre las referencias y las ediciones posteriores.
Describe expresamente el comportamiento que tolera errores por fila. «Omitir filas no válidas» significa que el cliente acepta una importación parcial y puede identificar los registros omitidos. Procesar cada lote de forma íntegra o no procesarlo es una alternativa razonable, especialmente cuando los objetos de dominio parciales podrían inducir a error. Ninguna de las dos opciones debe ocultarse tras un mensaje genérico de éxito.
Los trabajos en segundo plano resultan útiles cuando los tiempos de espera de las solicitudes, las desconexiones del navegador o el tiempo de procesamiento hacen inadecuada la ejecución síncrona. Guarda de forma persistente el estado necesario para reanudar, limita los reintentos y ofrece una forma de inspeccionar o detener los trabajos bloqueados. Una cola no aporta idempotencia automáticamente.
Define cuándo termina la importación y cómo obtener soporte
Concilia el conjunto aceptado con los registros confirmados mediante claves estables y compara después los campos importantes y los invariantes del dominio. Los recuentos son la primera comprobación. No detectan conjuntos del mismo tamaño que contienen registros distintos. La guía de verificación muestra ese fallo con SQL.
Registra los identificadores de los trabajos, las versiones, los recuentos, las categorías de errores, las duraciones y las transiciones de estado persistentes. Oculta los detalles sensibles de los errores de base de datos antes de mostrarlos si pueden revelar datos de otro tenant. Restringe el acceso a los archivos de diagnóstico e indica cuándo deben eliminarse.
Ofrece una página de resultados útil que siga disponible después de cerrar la pestaña: qué se aceptó, qué se confirmó, qué sigue sin resolverse y qué puede hacer el operador a continuación. Los archivos de corrección exportados también necesitan un tratamiento de las fórmulas de hojas de cálculo; usar comillas conforme a la sintaxis CSV no basta para impedir que una hoja interprete una celda peligrosa como fórmula.
Antes del lanzamiento, prueba una respuesta de commit perdida, dos envíos simultáneos del mismo lote, un contenido cambiado con una clave de reintento antigua, un permiso de tenant revocado, un cambio de esquema después de la vista previa y un trabajo cancelado con lotes confirmados. Estos casos revelan más sobre el importador que un gran archivo de demostración sin errores.