---
title: "Software choices checklist: all 92 rules · Agent Wranglers"
url: https://agentwranglers.se/playbook/stack/checklist
updated: 2026-10-21
licence: "All rights reserved"
---

# Software choices checklist

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

Every rule in the software choices playbook, by chapter, required rules first. Each links to its own page with how we built it and how to check it.

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/stack/checklist">Agent Wranglers software choices playbook</a>`. In code you write, add a comment next to it with the same link.

## How to choose

- [ ] **Required** [Pick software that still ships releases](https://agentwranglers.se/playbook/stack/how-to-choose/still-maintained): Choose software with a release in the last six months, and use a version that is still inside its published support window.
- [ ] **Required** [Prefer open source and pay only when nothing open does the job](https://agentwranglers.se/playbook/stack/how-to-choose/prefer-open-source): Pick open source software when an open source option passes the other tests. Pick a paid or proprietary service only when no open source option realistically does the job, and say why.
- [ ] **Required** [Keep an open licence or a way out](https://agentwranglers.se/playbook/stack/how-to-choose/open-licence-or-exit): Use software under an OSI-approved open source licence, or a managed service that exports all your data in a documented format.
- [ ] **Recommended** [Pick software proven in production for five years](https://agentwranglers.se/playbook/stack/how-to-choose/proven-for-five-years): Choose software whose first stable release is at least five years old, so its failure modes are known and written about.
- [ ] **Recommended** [Pick what most teams already use](https://agentwranglers.se/playbook/stack/how-to-choose/widely-used): Choose one of the three most used options in its category, so hiring, answers and integrations are easy to find.
- [ ] **Recommended** [Pick what AI tools already know](https://agentwranglers.se/playbook/stack/how-to-choose/known-to-ai-tools): Choose software that AI coding tools write correctly without extra documentation, and stay one major version behind the newest for six months after its release.
- [ ] **Recommended** [Pick software a new developer learns alone](https://agentwranglers.se/playbook/stack/how-to-choose/easy-to-learn): Choose software whose own documentation takes a new developer from nothing to a working example in one working day.
- [ ] **Recommended** [Keep one tool for each job](https://agentwranglers.se/playbook/stack/how-to-choose/one-tool-per-job): Keep one tool for each job, such as one test runner, one formatter and one database. Remove the old one when you switch.

## Languages and runtimes

- [ ] **Required** (Open source) [Use Node.js on an LTS line](https://agentwranglers.se/playbook/stack/languages-and-runtimes/nodejs-lts): Run JavaScript and TypeScript servers on an even-numbered Node.js line that is in Active or Maintenance LTS, and move up before its end date.
- [ ] **Recommended** (Open source) [Use TypeScript for web apps and APIs](https://agentwranglers.se/playbook/stack/languages-and-runtimes/typescript): Write browser code and server code in TypeScript with strict mode on, so one language and one set of types covers the whole app.
- [ ] **Recommended** (Open source) [Use Python for data work and as a second server language](https://agentwranglers.se/playbook/stack/languages-and-runtimes/python): Use a Python version in its bugfix phase for scripts, data jobs and APIs, and keep each project on one version.
- [ ] **Recommended** (Open source) [Use npm with a lock file for JavaScript packages](https://agentwranglers.se/playbook/stack/languages-and-runtimes/npm): Use the npm that ships with your Node.js line, commit `package-lock.json`, and install with `npm ci` in builds.
- [ ] **Recommended** (Open source) [Use pip and a virtual environment for Python packages](https://agentwranglers.se/playbook/stack/languages-and-runtimes/pip-and-venv): Install Python packages with pip into a virtual environment per project, from a file that pins every version.
- [ ] **Recommended** [Learn SQL and write it with parameters](https://agentwranglers.se/playbook/stack/languages-and-runtimes/sql): Every developer on a project with a database reads and writes plain SQL, even when the code uses a query builder or an ORM.
- [ ] **Avoid** [Leave runtimes that are out of support](https://agentwranglers.se/playbook/stack/languages-and-runtimes/end-of-life-runtimes): Never run a Node.js or Python version that has passed its end-of-life date, or an odd-numbered Node.js line in production.
- [ ] **Avoid** [Leave Yarn Classic](https://agentwranglers.se/playbook/stack/languages-and-runtimes/yarn-classic): Never start a project on Yarn 1, and move existing ones to npm or pnpm.

## Web frameworks

- [ ] **Required** (Open source) [Use Zod or Pydantic to check every input](https://agentwranglers.se/playbook/stack/web-frameworks/zod-pydantic): Parse every request body, query string, webhook and file at the boundary with a schema library, Zod in TypeScript or Pydantic in Python.
- [ ] **Recommended** (Open source) [Use React for the front end](https://agentwranglers.se/playbook/stack/web-frameworks/react): Build interactive screens with React, on a version that has been out for at least six months.
- [ ] **Recommended** (Open source) [Use Vite to build and serve the front end](https://agentwranglers.se/playbook/stack/web-frameworks/vite): Use Vite as the development server and build tool for any front end that is not inside a full-stack framework.
- [ ] **Recommended** (Open source) [Use Next.js when React pages need a server](https://agentwranglers.se/playbook/stack/web-frameworks/nextjs): Use Next.js when a React app needs pages rendered on the server, search engine traffic or server code next to the screens.
- [ ] **Recommended** (Open source) [Use Express for a Node.js server](https://agentwranglers.se/playbook/stack/web-frameworks/express): Use Express 5 for HTTP servers and APIs in Node.js.
- [ ] **Recommended** (Open source) [Use Django for a Python web app](https://agentwranglers.se/playbook/stack/web-frameworks/django): Use Django for a Python web app with a database, user accounts and an admin, on its current long-term support release.
- [ ] **Recommended** (Open source) [Use plain CSS before adding a CSS framework](https://agentwranglers.se/playbook/stack/web-frameworks/plain-css): Write styles in plain CSS files with custom properties, and add a utility framework only when the team already writes it.
- [ ] **Recommended** (Open source) [Use DOMPurify or nh3 to clean user HTML](https://agentwranglers.se/playbook/stack/web-frameworks/html-sanitiser): Clean any HTML that users write with DOMPurify in JavaScript or nh3 in Python, with a short allow list of tags and attributes.
- [ ] **Optional** (Open source) [Use FastAPI for a Python API](https://agentwranglers.se/playbook/stack/web-frameworks/fastapi): Use FastAPI for a Python service that only answers JSON, and pin its minor version.
- [ ] **Avoid** [Avoid Create React App](https://agentwranglers.se/playbook/stack/web-frameworks/create-react-app): Do not start or keep an app on Create React App, the react-scripts package.
- [ ] **Avoid** [Avoid AngularJS](https://agentwranglers.se/playbook/stack/web-frameworks/angularjs): Do not build on AngularJS, the 1.x framework in the angular package. Its successor, Angular, is a different framework.

## Databases and storage

- [ ] **Recommended** (Open source) [Use PostgreSQL for the main database](https://agentwranglers.se/playbook/stack/databases-and-storage/postgresql): Keep the main business data of a web app in PostgreSQL, on a major version with more than 12 months of support left.
- [ ] **Recommended** (Open source) [Use SQLite for a small or embedded database](https://agentwranglers.se/playbook/stack/databases-and-storage/sqlite): Use SQLite when one server process owns the data. Examples are a small site, a phone app, a test suite or a local tool.
- [ ] **Recommended** (Open source) [Use Redis 8 or Valkey for caches and queues](https://agentwranglers.se/playbook/stack/databases-and-storage/redis-or-valkey): Run Redis 8 or later, or Valkey, for caches, rate limits and job queues. Never run Redis 7.4 to 7.8, whose licences are not open source.
- [ ] **Recommended** (Open source) [Use a mature ORM for database code](https://agentwranglers.se/playbook/stack/databases-and-storage/orm): Write database code with Prisma in TypeScript and SQLAlchemy in Python, or with the Django ORM inside a Django project. Keep one ORM per codebase.
- [ ] **Recommended** (Open source) [Use the migration tool that comes with your ORM](https://agentwranglers.se/playbook/stack/databases-and-storage/migration-tool): Change the schema with the migration tool of the ORM you use, which is Prisma Migrate, Alembic for SQLAlchemy or Django migrations.
- [ ] **Recommended** (Open source) [Use PostgreSQL search first and OpenSearch when it falls short](https://agentwranglers.se/playbook/stack/databases-and-storage/full-text-search): Build search on PostgreSQL full-text search first. Add OpenSearch only when a measured need fails in PostgreSQL.
- [ ] **Recommended** (Open source) [Use the S3 API for files and SeaweedFS to host them](https://agentwranglers.se/playbook/stack/databases-and-storage/s3-api): Keep uploads and other files in object storage reached through the S3 API, with the endpoint and bucket in settings. Host it yourself on SeaweedFS.
- [ ] **Recommended** (Open source) [Use BullMQ or RQ for background jobs](https://agentwranglers.se/playbook/stack/databases-and-storage/background-jobs): Run slow or retried work in background jobs with BullMQ in Node.js or RQ in Python, both on Redis or Valkey.
- [ ] **Recommended** (Open source) [Use sharp or Pillow to process images](https://agentwranglers.se/playbook/stack/databases-and-storage/image-processing): Resize, turn upright and re-encode images with sharp in Node.js or Pillow in Python, and use no other image library.
- [ ] **Avoid** (Source available) [Avoid MongoDB as the default database](https://agentwranglers.se/playbook/stack/databases-and-storage/avoid-mongodb-default): Do not pick MongoDB Community Server as the main database of a new web app.
- [ ] **Avoid** (Open source) [Avoid the MinIO community edition](https://agentwranglers.se/playbook/stack/databases-and-storage/avoid-minio-community): Do not start new self-hosted object storage on the MinIO community edition, and plan a move off it.

## Testing and code quality

- [ ] **Recommended** (Open source) [Use pytest for Python tests](https://agentwranglers.se/playbook/stack/testing-and-code-quality/pytest): Write every Python test as a plain function run by pytest, with fixtures for shared setup.
- [ ] **Recommended** (Open source) [Use Jest for JavaScript unit tests](https://agentwranglers.se/playbook/stack/testing-and-code-quality/jest): Run JavaScript and TypeScript unit tests with Jest, with one config file at the project root.
- [ ] **Recommended** (Open source) [Use Playwright for browser tests](https://agentwranglers.se/playbook/stack/testing-and-code-quality/playwright): Drive browser tests with Playwright, in Chromium, Firefox and WebKit, against the built app.
- [ ] **Recommended** (Open source) [Use axe-core for accessibility tests](https://agentwranglers.se/playbook/stack/testing-and-code-quality/axe-core): Run axe-core on every page your browser tests open, and fail the test on any violation.
- [ ] **Recommended** (Open source) [Use ESLint and Prettier for JavaScript code](https://agentwranglers.se/playbook/stack/testing-and-code-quality/eslint-and-prettier): Lint JavaScript and TypeScript with ESLint and format it with Prettier, and fail the build on either.
- [ ] **Recommended** (Open source) [Use Ruff to lint and format Python](https://agentwranglers.se/playbook/stack/testing-and-code-quality/ruff): Lint and format Python with Ruff, in one config section, and fail the build on either.
- [ ] **Recommended** (Open source) [Use TypeScript in strict mode](https://agentwranglers.se/playbook/stack/testing-and-code-quality/typescript-strict): Write JavaScript projects in TypeScript with `strict` on, and run `tsc --noEmit` in the build.
- [ ] **Recommended** (Open source) [Use Pyright to check Python types](https://agentwranglers.se/playbook/stack/testing-and-code-quality/pyright): Add type hints to Python code and check them with Pyright in strict mode for new code.
- [ ] **Recommended** (Open source) [Use Renovate for dependency updates](https://agentwranglers.se/playbook/stack/testing-and-code-quality/dependency-bot): Let Renovate open dependency update pull requests, with one `renovate.json` at the repository root.
- [ ] **Recommended** (Open source) [Use Semgrep for static security scans](https://agentwranglers.se/playbook/stack/testing-and-code-quality/semgrep): Scan source code for security mistakes with Semgrep Community Edition in CI, with the rule sets named in the repository.
- [ ] **Recommended** (Open source) [Use TruffleHog to find leaked secrets](https://agentwranglers.se/playbook/stack/testing-and-code-quality/secret-scanner): Scan every pull request and the full Git history for secrets with TruffleHog, and fail the build on any verified or unknown finding.
- [ ] **Avoid** [Avoid Karma, Protractor and TSLint](https://agentwranglers.se/playbook/stack/testing-and-code-quality/retired-test-tools): Do not start with Karma, Protractor or TSLint, and move existing projects off them.

## Delivery and infrastructure

- [ ] **Recommended** (Free tier) [Use Git on GitHub for version control and code hosting](https://agentwranglers.se/playbook/stack/delivery-and-infrastructure/git-on-github): Keep every repository in Git, hosted on GitHub, with the default branch protected.
- [ ] **Recommended** (Free tier) [Use GitHub Actions for continuous integration](https://agentwranglers.se/playbook/stack/delivery-and-infrastructure/github-actions-ci): Run every build, test and deploy in GitHub Actions workflows stored in the repository, with each step a plain shell command.
- [ ] **Recommended** (Open source) [Use Docker and Docker Compose for containers](https://agentwranglers.se/playbook/stack/delivery-and-infrastructure/docker-and-compose): Package each service as a Docker image built from a Dockerfile, and describe the local stack in one Compose file.
- [ ] **Recommended** (Open source) [Use OpenTofu for infrastructure as code](https://agentwranglers.se/playbook/stack/delivery-and-infrastructure/opentofu): Describe all cloud resources in OpenTofu files kept in the repository, and apply them only from CI.
- [ ] **Recommended** (Open source) [Use Ubuntu LTS or Debian stable on servers](https://agentwranglers.se/playbook/stack/delivery-and-infrastructure/ubuntu-lts-or-debian): Run servers and container base images on a Ubuntu LTS release or Debian stable that is inside its standard security support.
- [ ] **Recommended** (Open source) [Use nginx or Caddy as the web server and reverse proxy](https://agentwranglers.se/playbook/stack/delivery-and-infrastructure/nginx-or-caddy): Put nginx or Caddy in front of every app server to serve TLS, static files, compression and redirects.
- [ ] **Recommended** (Free service) [Use Let's Encrypt for TLS certificates](https://agentwranglers.se/playbook/stack/delivery-and-infrastructure/lets-encrypt): Get every public certificate from Let's Encrypt through an ACME client that renews it by itself, such as certbot or Caddy.
- [ ] **Recommended** (Free tier) [Use a managed DNS and CDN that exports your zone](https://agentwranglers.se/playbook/stack/delivery-and-infrastructure/managed-dns-and-cdn): Host DNS and the CDN with a managed provider that exports the zone as a standard zone file, such as Cloudflare.
- [ ] **Recommended** (Open source) [Use SOPS for secrets](https://agentwranglers.se/playbook/stack/delivery-and-infrastructure/secrets-manager-or-sops): Keep runtime secrets in the repository encrypted with SOPS, and decrypt them only on the server or in CI.
- [ ] **Recommended** (Open source) [Use Trivy to scan images and dependencies](https://agentwranglers.se/playbook/stack/delivery-and-infrastructure/trivy): Scan every container image, lock file and infrastructure file with Trivy in CI, and pin Trivy itself by image digest or full commit hash.
- [ ] **Avoid** [Avoid HashiCorp tools under the Business Source License for new work](https://agentwranglers.se/playbook/stack/delivery-and-infrastructure/avoid-busl-hashicorp): Do not start new projects on Terraform or Vault releases under the Business Source License. Use OpenTofu and OpenBao, their open source forks.

## Operations tools

- [ ] **Recommended** (Open source) [Use OpenTelemetry to instrument your code](https://agentwranglers.se/playbook/stack/operations-tools/opentelemetry): Add traces, metrics and log context to your code with the OpenTelemetry API and SDK, and send them over OTLP to any backend.
- [ ] **Recommended** (Open source) [Use Prometheus for metrics](https://agentwranglers.se/playbook/stack/operations-tools/prometheus): Store and query numeric metrics with Prometheus, and alert on them with its rules and Alertmanager.
- [ ] **Recommended** (Open source) [Use Grafana for dashboards](https://agentwranglers.se/playbook/stack/operations-tools/grafana): Build dashboards in Grafana, with each dashboard saved as JSON in the repository.
- [ ] **Recommended** (Open source) [Use JSON logs and Loki to store them](https://agentwranglers.se/playbook/stack/operations-tools/json-logs-and-loki): Write one JSON object per log line to standard output, and ship the lines to Loki or another store that searches by label.
- [ ] **Recommended** (Open source) [Use GlitchTip for error tracking](https://agentwranglers.se/playbook/stack/operations-tools/glitchtip): Send every unhandled server and browser error to GlitchTip through the Sentry SDKs, tagged with the release. Fix new errors before the next deploy.
- [ ] **Recommended** (Open source) [Use Uptime Kuma on another provider for uptime checks](https://agentwranglers.se/playbook/stack/operations-tools/uptime-kuma): Check your public addresses from outside with Uptime Kuma, run at a different provider from the app.
- [ ] **Recommended** (Paid) [Use PagerDuty for paging and keep schedules as code](https://agentwranglers.se/playbook/stack/operations-tools/pagerduty): Page people through PagerDuty, and keep its schedules, escalation policies and services in Terraform in your repository.
- [ ] **Recommended** (Open source) [Use pg_dump and pgBackRest for Postgres backups](https://agentwranglers.se/playbook/stack/operations-tools/postgres-backups): Take a nightly `pg_dump` of every Postgres database, and add pgBackRest for point-in-time recovery once losing a day of data costs too much.
- [ ] **Optional** (Source available) [Use Sentry only for features GlitchTip lacks](https://agentwranglers.se/playbook/stack/operations-tools/sentry): Move from GlitchTip to Sentry only when you need a Sentry feature GlitchTip lacks, and name that feature in a decision record.
- [ ] **Avoid** [Avoid paging tools that are shutting down](https://agentwranglers.se/playbook/stack/operations-tools/ending-paging-tools): Do not start on Opsgenie or the open source Grafana OnCall, and move off them before they stop.

## Product services

- [ ] **Recommended** (Paid) [Use Stripe for payments](https://agentwranglers.se/playbook/stack/product-services/stripe-payments): Take card payments and subscriptions through Stripe's hosted checkout and official SDK, and pin the SDK's major version.
- [ ] **Recommended** (Paid) [Use Amazon SES to send transactional email](https://agentwranglers.se/playbook/stack/product-services/ses-transactional-email): Send transactional email through Amazon SES with DKIM on your own domain, and route every bounce and complaint back to your app.
- [ ] **Recommended** (Open source) [Use SimpleWebAuthn or py_webauthn for passkeys](https://agentwranglers.se/playbook/stack/product-services/passkey-library): Build passkey sign-in on SimpleWebAuthn in JavaScript or py_webauthn in Python, and never parse WebAuthn responses yourself.
- [ ] **Recommended** (Open source) [Use Keycloak when you need a sign-in server](https://agentwranglers.se/playbook/stack/product-services/keycloak-self-hosted): When two or more apps share sign-in, or you need single sign-on or SAML, run Keycloak and connect apps through standard OpenID Connect.
- [ ] **Recommended** (Open source) [Use the Web Push standard for browser push](https://agentwranglers.se/playbook/stack/product-services/web-push-standard): Send push messages to browsers through the Web Push standard with VAPID keys, using an open source library on the server.
- [ ] **Recommended** (Free service) [Use Firebase Cloud Messaging for Android and Apple app push](https://agentwranglers.se/playbook/stack/product-services/fcm-push): Send push messages to installed Android and Apple apps through Firebase Cloud Messaging with the Firebase Admin SDK.
- [ ] **Recommended** (Paid) [Use Twilio to send text messages](https://agentwranglers.se/playbook/stack/product-services/twilio-sms): Send text messages through a Twilio Messaging Service with the official SDK, and keep phone numbers in E.164 form.
- [ ] **Recommended** (Open source) [Use Better Auth or django-allauth for sign-in inside the app](https://agentwranglers.se/playbook/stack/product-services/sign-in-library): When one app runs its own sign-in, use Better Auth in TypeScript or django-allauth in Django, with users in your own database.
- [ ] **Recommended** (Open source) [Use MJML to build email layouts](https://agentwranglers.se/playbook/stack/product-services/mjml-email): Write each email layout in MJML, compile it to HTML in the build with strict validation, and fill in the values with your template engine.
- [ ] **Recommended** (Open source) [Use Playwright or WeasyPrint to turn HTML into PDF](https://agentwranglers.se/playbook/stack/product-services/html-to-pdf): Build invoices, receipts and reports as HTML and print them to tagged PDF with Playwright in Node.js or WeasyPrint in Python.
- [ ] **Optional** (Open source) [Use Plausible for analytics without cookies](https://agentwranglers.se/playbook/stack/product-services/plausible-analytics): Count visits and events with a self-hosted Plausible Community Edition, which sets no cookies and stores no raw IP addresses.
- [ ] **Avoid** [Avoid handling card numbers yourself](https://agentwranglers.se/playbook/stack/product-services/no-own-card-handling): Never let a card number, expiry date or security code reach your own servers, logs or database.
- [ ] **Avoid** [Avoid writing your own password and token code](https://agentwranglers.se/playbook/stack/product-services/no-own-auth-code): Never write your own password hashing, session tokens, WebAuthn parsing or OpenID Connect handling.

## AI software

- [ ] **Recommended** (Open source) [Use an open-weight model on vLLM or Ollama when it passes your evals](https://agentwranglers.se/playbook/stack/ai-software/open-weight-models): Run your eval set on an open-weight model served by an open source server, such as vLLM or Ollama. Use it whenever it reaches your pass threshold.
- [ ] **Recommended** (Paid) [Use each provider's official SDK to call models](https://agentwranglers.se/playbook/stack/ai-software/official-model-sdk): Call each model provider through its own official SDK, inside one module of your own. Add a shared abstraction only when you call two or more providers.
- [ ] **Recommended** (Open source) [Use Zod or Pydantic to define structured output](https://agentwranglers.se/playbook/stack/ai-software/zod-or-pydantic): Define each structured answer once, as a Zod schema in TypeScript or a Pydantic model in Python. Send its JSON Schema to the model and validate the reply with the same definition.
- [ ] **Recommended** (Open source) [Use pgvector in PostgreSQL before a separate vector database](https://agentwranglers.se/playbook/stack/ai-software/pgvector-first): Store embeddings in a pgvector column next to the rows they describe. Add a separate vector database only after a load test shows a limit PostgreSQL cannot meet.
- [ ] **Recommended** (Open source) [Use the Model Context Protocol to give agents your tools](https://agentwranglers.se/playbook/stack/ai-software/mcp-for-tools): Offer tools and data to outside AI agents as a Model Context Protocol server, built on an official MCP SDK.
- [ ] **Recommended** (Open source) [Use your test runner to run evals on a fixed example set](https://agentwranglers.se/playbook/stack/ai-software/evals-in-test-runner): Run AI evals as ordinary tests in the runner the project already uses, over a fixed set of examples kept in the repository.
- [ ] **Recommended** (Open source) [Use the coding agent that passes most of your own task set](https://agentwranglers.se/playbook/stack/ai-software/coding-agent-by-tests): Pick a coding agent by running your own fixed task set on each candidate. Keep its instructions in one AGENTS.md file that any agent can read.
- [ ] **Optional** (Open source) [Use Promptfoo only when it passes your own tests](https://agentwranglers.se/playbook/stack/ai-software/eval-tool-optional): Add an open source eval tool, such as Promptfoo, only when it runs your example set in CI and fails the build on a drop.

## Show the badge on your project

When your project passes every Required rule, you can show this badge on your site or in your README. It links to this checklist, so anyone can run the same checks.

```html
<a href="https://agentwranglers.se/playbook/stack/checklist"><img src="https://agentwranglers.se/badge.svg" alt="Checked against the Agent Wranglers software choices playbook" width="214" height="20"></a>
```

```markdown
[![Checked against the Agent Wranglers software choices playbook](https://agentwranglers.se/badge.svg)](https://agentwranglers.se/playbook/stack/checklist)
```
