Opus 5.5 writing test

Did Anthropic fix the writing?

Anthropic says Opus 5.5 puts the most important information up front and follows the writing rules you give it. Dan Shipper says it buries the main point. I gave the same 80 everyday prompts to four Claude models, twice: once with no instructions, once with five writing rules.

Short version. The style is fixed: zero em dashes, far less padding, fewer stock phrases. The structure is not: answers are just as long as Opus 5, lean harder on headers, and lead with the answer about as often. And when you hand it writing rules, it follows them less often than Opus 5 or 4.6, mostly by running past word limits.

Em dashes in 80 answers

No instructions. Plain count of the — character.

  • Opus 4.6
    443
  • Opus 5
    427
  • Opus 5.5
    0
  • Fable 5.1
    227

Padded, per Jev

No instructions. A good human expert would cut a third or more.

  • Opus 4.6
    33%
  • Opus 5
    29%
  • Opus 5.5
    13%
  • Fable 5.1
    16%

Answers the question in the first sentence

48 questions: decisions, explanations, debugging, advice, summaries, reviews.

  • Opus 4.6
    75%
  • Opus 5
    90%
  • Opus 5.5
    87%
  • Fable 5.1
    83%

Median words per answer

No instructions. Opus 5.5 is not shorter.

  • Opus 4.6
    307
  • Opus 5
    359
  • Opus 5.5
    360
  • Fable 5.1
    337

Follows all five writing rules

Answer first, no em dashes, no headers, under 200 words, no closing offer.

  • Opus 4.6
    78%
  • Opus 5
    61%
  • Opus 5.5
    39%
  • Fable 5.1
    55%

Blows through the 200-word limit

Share of answers at 210+ words when told to stay under 200.

  • Opus 4.6
    4%
  • Opus 5
    3%
  • Opus 5.5
    16%
  • Fable 5.1
    5%

Uses markdown headers

No instructions.

  • Opus 4.6
    81%
  • Opus 5
    39%
  • Opus 5.5
    73%
  • Fable 5.1
    30%

Ends with an offer to help

No instructions.

  • Opus 4.6
    35%
  • Opus 5
    11%
  • Opus 5.5
    4%
  • Fable 5.1
    8%

Read the answers yourself

Opus 4.6293 wordsanswer first5 em dashes
# Use PostgreSQL For a small SaaS with user accounts, billing, and JSON settings, Postgres is the stronger choice. Here's why: ## Why Postgres fits perfectly - **User accounts & billing are relational by nature** — users have invoices, invoices have line items, plans have features. Foreign keys and joins make this clean and safe. - **Postgres handles JSON natively** — the `jsonb` column type gives you the flexible-schema storage you'd use MongoDB for, *with* the ability to index and query inside it. - **Transactions matter for billing** — ACID compliance means you won't end up with a charged card but no recorded subscription. - **One database to operate** — simpler infra, simpler backups, simpler deploys. ## Quick schema sketch ```sql CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email TEXT UNIQUE NOT NULL, settings JSONB DEFAULT '{}'::jsonb, -- flexible JSON here created_at TIMESTAMPTZ DEFAULT now() ); CREATE TABLE subscriptions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES users(id), plan TEXT NOT NULL, status TEXT NOT NULL, billing_info JSONB, -- flexible JSON here too current_period_end TIMESTAMPTZ ); ``` You get rigid structure where it matters and flexible JSON where you need it. ## When MongoDB *would* make sense instead - Your data is mostly documents with deeply nested, unpredictable shapes - You're doing high-volume writes of event/log data - You have no relational concerns at all None of those describe "user accounts + billing + some settings." ## Hosting options to get started fast | Service | Free tier | Notes | |---|---|---| | **Supabase** | 500 MB | Postgres + auth + APIs built-in | | **Neon** | 0.5 GB | Serverless Postgres, scales to zero | | **Railway** | $5 credit | Simple deploy | | **Render** | Free tier | Managed Postgres | **TL;DR** — Postgres gives you relational integrity for the parts that need it and `jsonb` for the parts that don't. It's the default right answer for this kind of app.
Opus 5331 wordsanswer first1 em dash
**Postgres.** For that workload it's the clearer choice. **Why it fits your case:** - **Billing needs transactions and correctness.** Subscriptions, invoices, credits, and payment state are highly relational and unforgiving of drift. Postgres gives you real foreign keys, constraints, and multi-table ACID transactions by default. - **User accounts are relational.** Users → orgs → memberships → roles → subscriptions. That's joins, and joins are where Postgres shines and where document stores push you into duplicating or manually re-fetching data. - **JSON settings are a solved problem.** `jsonb` columns give you schemaless flexibility exactly where you want it, plus GIN indexes and query operators if you ever need to filter on them: ```sql create table users ( id uuid primary key, email text unique not null, settings jsonb not null default '{}' ); create index on users using gin (settings); ``` You get Mongo's flexibility for the 5% of your schema that needs it, without giving up structure for the 95% that doesn't. - **Operationally boring.** Managed Postgres is everywhere (Neon, Supabase, RDS, Fly, Render), cheap at small scale, and every ORM/tool targets it well. **When Mongo would actually win:** massive write volume of heterogeneous documents, deeply nested data you always read as a whole blob, or a schema genuinely unknown at design time. None of those describe "user accounts + billing." **Practical advice:** - Keep money-related data in proper typed columns, never in JSON. You'll want to `SUM()`, index, and reconcile it. Use `numeric`, not `float`. - Use `jsonb` for user/tenant preferences, feature flags, and webhook payload archives. - Add a migration tool from day one (Prisma Migrate, Drizzle, Alembic, or plain SQL files). Schema drift is the thing that actually bites small teams. - Store raw Stripe (or whichever provider) webhook events in a `jsonb` column alongside a few extracted columns. Great for debugging billing disputes. The one real risk with Postgres at small scale is connection exhaustion if you're on serverless — put PgBouncer or a pooler in front, or use a provider that includes one.
Opus 5.5324 wordsanswer first
**Use Postgres.** For your use case it's not a close call. **Why Postgres fits:** - **User accounts and billing are relational.** Users belong to organizations, organizations have subscriptions, subscriptions have invoices, and invoices have line items. Foreign keys, joins, and constraints model this naturally and keep the data consistent. - **Billing needs strong guarantees.** Multi-row ACID transactions, unique constraints (for example, one active subscription per org), and `CHECK` constraints stop bad data at the database level. You don't want to discover a double-charge bug in application code. - **JSON settings are covered.** `JSONB` columns let you store flexible per-user or per-org settings, index them with GIN indexes, and query into them (`settings->>'theme'`). You get document flexibility where you need it and structure everywhere else. - **Ecosystem and tooling.** Every major ORM (Prisma, Drizzle, SQLAlchemy, ActiveRecord, Django) has first-class support. Managed hosting is cheap and easy (Neon, Supabase, RDS, Railway, Render). Stripe's own data model maps cleanly onto relational tables. - **Room to grow.** Postgres handles full-text search, row-level security, pub/sub (`LISTEN/NOTIFY`), job queues, and vector search (`pgvector`). You can avoid adding extra infrastructure for a long time. **When MongoDB would make sense:** - Most of your data is truly schemaless or deeply nested documents with few relationships (content blobs, event logs, CMS-like data). - You need built-in horizontal sharding at massive write volume from day one. A small SaaS almost certainly doesn't. **A typical shape:** ```sql create table users ( id uuid primary key default gen_random_uuid(), email text unique not null, settings jsonb not null default '{}', created_at timestamptz not null default now() ); create table subscriptions ( id uuid primary key default gen_random_uuid(), user_id uuid not null references users(id), stripe_subscription_id text unique not null, status text not null check (status in ('active','past_due','canceled')), current_period_end timestamptz not null ); ``` Postgres with JSONB for settings gives you relational safety for accounts and money, plus flexibility for the fuzzy parts.
Fable 5.1309 wordsanswer first2 em dashes
**Postgres.** For this use case it's not really close. **Why:** - **User accounts + billing are relational by nature.** Users → subscriptions → invoices → payments. You want foreign keys, unique constraints on emails, and transactions so a failed charge doesn't leave a half-updated account. Postgres gives you this for free; in Mongo you end up reimplementing it in app code. - **Billing needs correctness guarantees.** ACID transactions, exact `NUMERIC` types for money (no float rounding), and strong constraints matter a lot when you're charging people. Mongo has multi-document transactions now, but it's bolted on and the ecosystem doesn't lean on it. - **The "some JSON settings" part is a non-issue.** Postgres's `JSONB` column handles this very well — you get flexible schemaless storage for settings/preferences, can index into it, and query it with `->>` operators. This is the single most common reason people reach for Mongo, and Postgres covers it. - **Ecosystem fit.** Stripe webhooks, auth libraries (Auth.js, Lucia, Devise, etc.), and ORMs (Prisma, Drizzle, SQLAlchemy, ActiveRecord) all have first-class Postgres support and mature migration tooling. - **Hosting is cheap and easy.** Neon, Supabase, Railway, Fly, RDS — all have free/small tiers with backups and point-in-time recovery. **When Mongo would actually make sense:** highly variable document shapes with no clear relationships, very high write throughput on unstructured event data, or your team already has deep Mongo experience and no SQL background. None of those apply to "small SaaS with accounts and billing." **Practical suggestion:** Postgres with proper tables for users/organizations/subscriptions/invoices, a `JSONB` column (e.g. `users.settings` or `organizations.settings`) for the flexible bits, and a typed ORM so you're not writing raw SQL for everything. You can always add a separate store later if you genuinely hit a document-shaped problem, but you almost certainly won't at small scale.