Go on One VPS: Production Handbook

Cómo escribir un servicio en Go que puedas dejar corriendo en un servidor: apagado, timeouts, memoria y systemd, con un servicio de referencia funcional detrás de cada listado.

Comprar en Polar: $39 Pago único · v0.1.0 · descarga inmediata con Polar

Portada de Go on One VPS: Production Handbook
Salida de una ejecución de pruebas real, no una maqueta.

Para quién es

Escribes Go y tu servicio corre en una sola máquina Linux bajo systemd. Quizá es una API con un worker en segundo plano y SQLite, quizá un receptor de webhooks, quizá una herramienta interna de la que depende toda la empresa. Funciona. Lo que quieres saber es qué pasa en los bordes: un deploy con peticiones en vuelo, un cliente que nunca termina de enviar los headers, un container con muy poca memoria, una caída a las 3 de la madrugada.

Esto no es un tutorial de Go. Da por hecho que conoces el lenguaje y que ya has publicado algo. Si buscas una introducción a las goroutines, los libros de Go más conocidos son mejor punto de partida.

Qué contiene

Un libro de 16 capítulos, de unas 2,000 líneas, y un pequeño servicio de referencia del que sale cada listado de Go del libro. Un script comprueba que cada uno de los 60 bloques de código coincide con el código fuente probado, así que nada del texto es un fragmento que nadie haya ejecutado.

#Capítulo
1Estructura de un proyecto para un servicio pequeño
2Configuración desde el entorno: valida todo y falla pronto
3Logging estructurado con log/slog, sin filtrar secretos
4Timeouts del servidor HTTP
5Graceful shutdown
6Health frente a readiness
7Context, cancelación y comprobaciones de fugas de goroutines
8Acceso a bases de datos con SQLite: WAL, un solo escritor, migraciones
9Errores y panics
10Métricas y pprof, con seguridad
11Testing
12Compilación: binarios estáticos y reproducibles
13systemd: unidad, hardening, reinicio, parada
14Memoria: qué hace un proceso Go bajo presión
15Deploy con carpetas de release
16Bugs habituales en producción, cada uno con una comprobación que lo detecta

También recibes el servicio de referencia (biblioteca estándar y un driver de SQLite), un generador de carga, un pequeño experimento de memoria, la unidad de systemd y un Dockerfile, tres checklists y un banco de pruebas en Docker que repite todas las comprobaciones desde un container limpio. Incluimos la salida de nuestra última ejecución completa para que puedas compararla con la tuya.

Qué muestran las pruebas

Los capítulos sobre apagado y systemd se apoyan en tests que arrancan el binario real y le envían señales reales.

Qué hicimosQué pasó
SIGTERM con un trabajo de 1.5 s en cursoLas conexiones nuevas se rechazaron a los 11 ms, la petición en curso terminó a los 1.399 s y el proceso salió con código 0 a los 1.669 s
SIGTERM a un servicio inactivoSalida en 2 ms
SIGTERM con un trabajo de 9 s y un límite de apagado de 500 msSalida a los 515 ms con código 1, el trabajo vuelve a la queue
Cliente que envía los headers despacio, con un timeout de headers de 300 msConexión cortada a los 295 ms
systemctl stop con una petición de 3 s en cursoLa petición devolvió 200 y la parada tardó 3.19 s
kill -9 bajo systemdDe nuevo sano 2.10 s después
Dos builds desde directorios distintosBinarios idénticos byte a byte (y distintos cuando se omite -trimpath, como control)

La unidad de systemd incluye opciones de hardening, y el resultado lo leemos del proceso en ejecución en lugar de fiarnos del archivo: sin capabilities, con un filtro seccomp, /usr y /etc en solo lectura y un límite de memoria. systemd-analyze security dio a la unidad una puntuación de exposición de 1.4.

Rendimiento y memoria

Configuración: Docker Desktop en un portátil con Apple Silicon, 8 CPU, el servicio, el generador de carga y la base de datos en un mismo container, 16 clientes, tres ejecuciones de 8 segundos por modo.

ModoPeticiones por segundo (3 ejecuciones)
EscriturasDe 9,190 a 11,189 (p99 de 8.4 a 11.7 ms)
LecturasDe 13,541 a 18,421
Endpoint de healthDe 23,032 a 26,757

La memoria residente fue de 13 MiB en reposo y de 23 MiB después de la prueba de carga, con un pico de 25 MiB.

GOMEMLIMIT, medido

El capítulo 14 no se limita a decirte que definas GOMEMLIMIT y sigas adelante. Ejecuta un programa pequeño con un heap vivo de 40 MiB dentro de un container limitado a 80 MiB. Sin límite, el OOM killer lo mató en 3 de 3 ejecuciones. Con GOMEMLIMIT=56MiB sobrevivió 3 de 3, a cambio de unas cuatro veces más ciclos de garbage collection. El libro también explica por qué el límite es blando y qué implica eso a la hora de dimensionar.

Requisitos y formato

Go 1.24 o posterior. Docker, solo si quieres repetir el banco de pruebas. Todo es Markdown, código Go, shell y archivos de configuración: sin bloqueo de PDF, sin cuenta, léelo donde quieras.

Preguntas frecuentes

¿Es un libro para principiantes?

No. Da por hecho que ya escribes Go. Trata del lado de producción: qué hace el proceso cuando algo sale mal.

¿Cubre Postgres?

El servicio de referencia y sus tests usan SQLite. El capítulo de bases de datos también da pautas para Postgres.

¿En qué se diferencia del Go Webhook Receiver Starter?

El starter es un producto pequeño que pones a correr. El manual explica el razonamiento y las pruebas detrás de un servicio Go que se porta bien, y usa otro servicio de referencia.

¿Puedo usar el código en mis propios proyectos?

Sí, en tus proyectos y en los servidores tuyos o de tu empresa. Por favor, no revendas ni redistribuyas el libro ni el kit.

Historial de cambios

  • 0.1.0: primera versión.

Leer más

Obtener

Comprar en Polar: $39

Polar, como merchant of record, se ocupa del pago, los impuestos y las facturas. Al terminar la compra recibes un enlace de descarga.