Skip to main content
Back to the field guide

A field guide to the /spine-service skill

AI Production Backend Service Generator

Most service scaffolds skip the production essentials. /spine-service ships config validation, health checks, graceful shutdown, structured logs, and service discovery from day one.

Spine · Backend9 min readMarch 3, 2026

Most new backend services launch with the same set of missing pieces. The config is read directly from process.env without validation, so a missing variable surfaces as a runtime crash an hour after deploy rather than a startup failure. The health check returns 200 always, so the load balancer never sees the service as unhealthy. The shutdown handler does not exist, so a deploy or autoscale event drops in-flight requests. The logging is console.log strings nobody can grep. The service is registered nowhere, so the next service that needs to call it has to look up the IP. Each missing piece is small in isolation. Together they are the difference between a service that operates well and a service that produces a postmortem the first time something goes wrong.

A production-ready service has these pieces from day one because adding them later is painful. Config validation has to happen at startup so failures are loud. Health checks have to actually check the dependencies. Graceful shutdown has to drain in-flight requests with a deadline. Structured logging has to use consistent fields with trace context. Service discovery has to register with whatever the environment uses. The discipline takes a focused day to set up correctly per service, and that day is exactly what the team did not budget. The /spine-service skill produces the foundation as the default rather than the cleanup pass.

Why generalist AI ships incomplete scaffolds

Ask Cursor or ChatGPT for a new service. You get the entry point: framework setup, one route, the listen call. The output runs. It also has no startup validation, no real health check, no shutdown handling, generic logging, and no observability hooks. The generalist tool is producing what the SDK tutorials show, and the tutorials show the smallest runnable example. The smallest runnable example is the wrong thing to ship to production because it is missing the operational pieces that production requires.

The deeper issue is that the operational pieces are not visible in the prompt. The team asks for a service; the operational concerns are implicit. A senior engineer hears "build a new service" and adds the config validator, the health check, the shutdown handler, the structured logger automatically, because they have lived through the absence. A generalist tool hears the same prompt and produces what was asked, which is the smallest runnable thing. The fix is to encode the operational baseline in the tool, which is what /spine-service does.

What a production-ready service requires

A production-ready service ships with five layers. Config: every environment variable validated at startup with type coercion and required-vs-optional, with a clear error if anything is missing. Health checks: a /healthz for liveness (process is up) and a /readyz for readiness (dependencies are reachable, the service is ready to accept traffic). Graceful shutdown: catch SIGTERM, stop accepting new requests, wait for in-flight requests to complete with a deadline, then exit cleanly. Structured logging: JSON logs with consistent fields (timestamp, level, message, trace ID, request ID), routed to stdout for the platform's log shipper. Service discovery: register with the environment's discovery mechanism (Consul, Kubernetes, ECS service connect) so peers can find the service by name.

These layers compose. Without graceful shutdown, the deploy drops requests; without health checks, the rolling update declares an unhealthy pod ready and ships traffic to a broken service; without config validation, a missing variable produces a 500 storm an hour after deploy. The discipline of setting up all five together is the discipline of treating the service as something operators will run, not as something developers will demo.

How /spine-service works

Step one: detect the stack

When invoked, /spine-service reads the project to detect the language and framework: Node.js with NestJS or Express or Fastify, Python with FastAPI or Flask, Go with chi or echo, Rust with axum, Java with Spring Boot. The detection drives the generated code so the service uses the project's existing patterns rather than introducing new ones.

Step two: config validator and health checks

The config validator runs at startup using a schema library (Zod, Pydantic, validator pkg). Required variables that are missing produce an explicit error and prevent the process from starting. Optional variables have defaults. Type coercion handles the string-from-env coming back as the right type. Health checks split into liveness (/healthz, returns 200 if the process is alive and not deadlocked) and readiness (/readyz, returns 200 if dependencies like the database and message broker are reachable). The split lets Kubernetes restart a deadlocked pod via liveness while routing traffic correctly via readiness.

Step three: graceful shutdown

The shutdown handler catches SIGTERM (from Kubernetes or the orchestrator) and runs the shutdown sequence: stop accepting new requests at the listener, wait for in-flight requests to complete with a configured deadline (typically 30 seconds), close database connections cleanly, exit with status 0. The order matters: stop accepting first so new requests fail fast at the load balancer, then drain so the requests already in-flight complete. Without the order, in-flight requests get cut off when the listener closes.

Step four: structured logging and service discovery

Logging is structured JSON to stdout with consistent fields per entry. Trace context is propagated via OpenTelemetry headers so a request crossing services produces correlated logs. Service discovery registers the service with the environment's mechanism: Kubernetes services for the cluster case, Consul or service connect for VM-based environments. The registration is automatic on startup and deregistration is part of the graceful shutdown sequence.

Splitting health checks into /healthz and /readyz is the single most useful operational decision for a Kubernetes service. Liveness restarts deadlocked pods; readiness gates traffic during deploys. Combining them into one endpoint loses the distinction and produces either too-aggressive restarts or stuck deploys.

Tonone's /spine-service skill bootstraps backend services with config validation, health checks, graceful shutdown, structured logging, and service discovery from day one.

When to use /spine-service, and when not to

/spine-service is the right call when starting a new backend service from scratch and wanting a production-ready foundation, or when an existing service is missing the operational layers and the team is hardening it before the next launch. The signal is when the team would otherwise copy from another service that itself was missing pieces.

Skip the skill for short-lived scripts and one-off automation (the operational layers are overhead). For API design specifically, /spine-api is the right call. For backend performance work on an existing service, /spine-perf is calibrated to that work.

CapabilityTononeGeneralist chatbotCursor / Copilot
Config validation at startupYes, schema-validated, fail-fastDirect env accessNot in scope
Liveness vs readiness splitYes, both endpointsSingle /health returning 200Not in scope
Graceful shutdown with drainYes, SIGTERM handler with deadlineProcess exits abruptlyNot in scope
Structured JSON loggingYes, with trace contextconsole.log stringsWhatever framework default
Service discovery registrationYes, environment-appropriateNot configuredNot in scope

A worked example: bootstrapping a NestJS service

Suppose the brief is: bootstrap a new NestJS service that will run in Kubernetes. Run /spine-service.

typescript
// src/config.ts
import { z } from 'zod';

const ConfigSchema = z.object({
  PORT: z.coerce.number().int().positive().default(8080),
  DATABASE_URL: z.string().url(),
  REDIS_URL: z.string().url(),
  LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
  SHUTDOWN_GRACE_SECONDS: z.coerce.number().int().positive().default(30),
});

export const config = ConfigSchema.parse(process.env);
// Throws at startup if anything is missing or invalid.

// src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { config } from './config';
import { logger } from './logger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { logger });
  app.enableShutdownHooks();

  // Health endpoints registered separately
  // /healthz - liveness, returns 200 always while process is up
  // /readyz - readiness, returns 200 only when DB + Redis reachable

  const server = await app.listen(config.PORT);
  logger.info({ port: config.PORT }, 'service started');

  // Graceful shutdown
  for (const sig of ['SIGTERM', 'SIGINT']) {
    process.on(sig, async () => {
      logger.info({ signal: sig }, 'shutdown initiated');
      server.close(); // stop accepting new connections
      // app.close drains in-flight requests with grace deadline
      await Promise.race([
        app.close(),
        new Promise((_, rej) =>
          setTimeout(
            () => rej(new Error('shutdown deadline exceeded')),
            config.SHUTDOWN_GRACE_SECONDS * 1000,
          ),
        ),
      ]);
      logger.info('shutdown complete');
      process.exit(0);
    });
  }
}
bootstrap().catch((e) => {
  logger.error({ err: e }, 'startup failed');
  process.exit(1);
});

Config validates at startup. SIGTERM drains in-flight requests with a deadline. Health endpoints expose liveness and readiness separately. Structured logging routes JSON to stdout for the cluster's log shipper. Service discovery registers via the Kubernetes Service object created alongside this Deployment. Day-one production posture rather than the demo posture.

/spine-service produces the foundation. For the API design layered on top, /spine-api is the right call. For the system design that precedes a multi-service buildout, /spine-design is the right entry point. For observability hooks beyond the basic structured log, /vigil-instrument adds RED metrics and tracing.

Install

/spine-service ships with the Spine agent in the Tonone for Claude Code package. Install Tonone, invoke /spine-service from any Claude Code session, and the skill produces a production-ready service foundation calibrated to the project's stack.

1. Add to marketplace

$ claude plugin marketplace add tonone-ai/tonone

2. Install Spine

$ claude plugin install spine@tonone-ai

Services that operate well are the ones built for the operator from day one. The skill is built so the operational baseline is the default.

Frequently asked questions

What does /spine-service do?
It bootstraps a new backend service with the operational layers production needs from day one: config validation at startup, liveness and readiness health checks, graceful shutdown with request draining, structured JSON logging with trace context, and service discovery registration.
What languages and frameworks does /spine-service support?
Node.js (NestJS, Fastify, Express, Hono), Python (FastAPI, Flask), Go (chi, echo), Rust (axum), Java (Spring Boot), and Bun runtime variants. The skill detects which the project uses and matches it.
How is /spine-service different from a framework starter?
Framework starters demonstrate the framework. /spine-service produces the operational baseline (validation, health, shutdown, logging, discovery) calibrated to the deploy environment.
When should I use /spine-service?
When starting a new backend service or microservice from scratch, or when an existing service is missing the operational layers and the team is hardening it before launch.
Why split liveness and readiness?
Liveness restarts deadlocked pods; readiness gates traffic during deploys and outages. Combining them into one endpoint loses the distinction and produces either too-aggressive restarts (when the dependency is briefly unavailable) or stuck deploys (when the pod is up but warming caches).
How do I install /spine-service?
Install Tonone for Claude Code via the get-started guide at tonone.ai/get-started. /spine-service ships with the Spine agent and is invoked as a slash command in any Claude Code session. Tonone is free and MIT-licensed.
Is /spine-service free?
Yes. The skill is part of Tonone, which is MIT-licensed. The only cost is Claude Code token usage during the work.
Does /spine-service handle observability?
It produces the structured logging baseline. For full observability (RED metrics, distributed tracing, custom application metrics), /vigil-instrument extends the service with the additional layers.

Pairs well with