The fifteenth time an engineer at your company creates a new service, the boilerplate has become a tax. Logging setup, health checks, deployment configs, observability instrumentation, secret access, CI/CD pipelines, CODEOWNERS files — every new service needs them, and every team configures them slightly differently. A service template is the answer: a generator that scaffolds a new service with all the cross-cutting concerns already wired in.
This is the "paved road" concept from platform engineering: there is a known-good way to create a new service, and following it is faster than doing it yourself. The template is the artifact that makes the paved road real.
What a Template Includes
A useful service template scaffolds a service that, on day one, has:
- A health check endpoint
- Structured logging configured to the standard format and destination
- Metrics emitting in the standard format (Prometheus, OTLP, whatever the platform uses)
- Distributed tracing instrumentation
- A Dockerfile that produces a runnable image
- CI/CD pipeline definitions (GitHub Actions, GitLab CI, etc.)
- Kubernetes manifests or equivalent deployment specs
- Secret access wired up to the platform's secret manager
- A
CODEOWNERSfile, a license, a code of conduct - A
README.mdwith team-specific placeholders to fill in - Local development setup (Compose or Devcontainer)
- Linting, formatting, and pre-commit hooks
- A working test suite with a few example tests
The point is not that every service needs every piece — it is that opting out is faster than opting in. A new service starts working and only the team's actual business logic is missing.
What a Template Should Not Include
A template that tries to include too much becomes a liability. Things to leave out:
- Business logic. The template scaffolds infrastructure, not features.
- One-off integrations. If only one team will ever use a specific integration, do not bake it in.
- Anything experimental. Templates set norms. Experimental code in a template makes the experiment a norm.
- Hard-coded names or assumptions. A template should generate code with the team's name, not the platform team's name.
The boundary is roughly: "if every team will need this, include it. If only some teams will need it, make it an opt-in feature in the template."
Tooling Options
Several tools generate scaffolded projects from templates:
| Tool | Notes |
|---|---|
| Cookiecutter | Python-based, language-agnostic, widely used |
| Backstage Software Templates | Integrates with Spotify's Backstage developer portal |
| Yeoman | JS-based, older but still used |
| Plop.js | Lightweight for Node.js teams |
| Custom shell or PHP scripts | Often a fine starting point |
The choice matters less than the discipline. A Cookiecutter template that is well-maintained beats a Backstage template that is unmaintained, and vice versa.
A Concrete Example
A template for a new Laravel microservice might prompt for:
service_name— what is this service called?team— which team owns it?port— which port does it listen on?database— does it need a database? Postgres / MySQL / none?queue— does it need a queue worker?external_apis— which platform-managed external APIs does it talk to?
Then generates:
my-new-service/
├── app/
│ ├── Http/Controllers/HealthCheckController.php # /healthz, /readyz
│ ├── Providers/
│ └── ...
├── config/
│ ├── logging.php # structured JSON logging
│ └── telemetry.php # OTLP exporter config
├── deploy/
│ ├── Dockerfile
│ └── k8s/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── ingress.yaml
├── .github/
│ ├── workflows/ci.yml
│ └── CODEOWNERS
├── README.md
└── ...
The CI workflow is the team standard. The Dockerfile builds the team standard image. The Kubernetes manifests use the team standard labels and resource requests. The README.md is filled in with the team name from the template prompt.
A new service is ready to deploy on the day it is generated.
Templates Are Living Code
A common mistake is treating templates as one-time artifacts. The platform evolves: a new observability standard, a new CI runner, a new way of injecting secrets. The template has to evolve with it.
Two patterns make this manageable:
Track template version in generated services. Every service records the template version it was generated from. The platform team can see which services are running an outdated template.
# .platform.yaml in generated service
template:
name: laravel-microservice
version: 2026.05.0
generated_at: 2026-05-11T14:00:00Z
Automated migration. When a template changes, a migration script can apply the changes to existing services. Sometimes this is automatic (file replacements); sometimes it is "open a PR for the team to review."
Without these patterns, services drift. The template's value collapses if every service is a snowflake of "I was generated when the template was different, please don't change anything."
The Adoption Problem
A template that nobody uses solves no problem. The hardest part of running a service-template system is adoption — convincing teams that following the paved road is faster than reinventing.
Things that help:
- Make the paved road genuinely faster. If using the template adds an hour and using your own setup saves an hour, teams will go off-road. Reverse those costs.
- Make off-road expensive. New services not generated from the template should not get default access to platform services — secrets, observability, deployment. Earning those without the template is real work.
- Invest in the developer experience. The template's first run should be one command. The generated service should boot locally with one command. If either is more than one command, fix it.
- Eat your own dog food. The platform team's own services should be generated from the template.
When You Need Multiple Templates
Most platforms eventually need more than one template. Different runtimes (Laravel vs Node vs Go), different shapes (HTTP service vs queue worker vs scheduled job), different deployment targets (Kubernetes vs Lambda vs ECS).
The risk is that templates multiply faster than the platform team can maintain them. Each template has a cost: keeping it up to date, fixing bugs, adopting new platform conventions. Five well-maintained templates beat fifteen mostly-broken ones.
A reasonable rule: a new template is justified when at least three teams want to start services that the existing templates do not cover well. Below that, the differences are usually small enough to add as options inside an existing template.
What This Costs
A real service-template system requires a team — usually the platform team — that owns the templates as production code. They write tests for the templates, they version them, they document them, they migrate teams to new versions. It is a real investment.
For a small company (under maybe 50 engineers), the investment usually does not pay back. The boilerplate cost is small, and a wiki page describing the conventions is enough. The pattern becomes valuable when the cost of inconsistent service setup — failed deploys, incomplete observability, security gaps — outweighs the investment in template tooling.
The Quiet Benefit
Beyond the velocity benefit, templates carry standards forward. The team that follows the template inherits the platform team's decisions about logging, tracing, secrets, and deployment. New engineers do not have to learn all of that — they get it for free. The platform's expertise propagates without anyone having to teach it.
That second-order benefit is often what makes the template investment worth it. The first-order benefit is speed. The second-order benefit is institutional knowledge baked into code.
Building out a platform team and wondering whether service templates are the right next investment? We help teams pick the platform engineering work that actually moves the needle. scopeforged.com