Skip to content
lazy devs
3 min readLazy Devs

Ship a fast marketing site without a database

Most agency sites do not need a database. Here is how we build static, SEO-first sites that load instantly and cost almost nothing to run.

A surprising number of marketing sites ship with a database they never needed. A Postgres instance, an ORM, a connection pool, and a monthly bill, all to serve content that changes a few times a month. For most agency, product and brochure sites, that is the wrong default. It adds cost, latency and a moving part that can break at 3am, in exchange for flexibility you are not using.

The approach we reach for first is the opposite: render everything to static HTML at build time, serve it from a CDN, and skip the runtime data layer entirely. This very site is built that way. Here is how it works and where the line actually is.

Why static wins for content sites

When every page is prerendered, there is no server work on the request path. The CDN returns bytes that already exist. That has three compounding effects:

  • Speed. Time to first byte is a CDN edge lookup, not a cold serverless function plus a database round trip. The page is already a file.
  • Reliability. There is no connection pool to exhaust and no slow query to time out under a traffic spike. A launch-day surge is just more CDN reads.
  • Cost. Static assets are close to free to serve, even at scale. You are not paying for a database that sits idle 95% of the day.

Static rendering is also the foundation of good performance and SEO engineering: the fastest request is the one your server never has to think about.

Where the content actually lives

Without a database, content needs a home. We use local MDX files compiled at build time. Each post or page is a file with typed frontmatter, validated when the site builds:

const posts = defineCollection({
  name: "Post",
  pattern: "blog/**/*.mdx",
  schema: s.object({
    title: s.string().max(99),
    excerpt: s.string().max(160),
    date: s.isodate(),
    tags: s.array(s.string()).default([]),
    content: s.markdown(),
  }),
});

The build step validates every file against that schema. A typo in a date, a missing title, or a meta description that runs too long fails the build instead of shipping broken metadata to production. Your content layer gets the same type safety as the rest of the codebase, and editors work in plain Markdown.

For teams that want a friendlier editing experience, the same pattern works with a headless CMS feeding content in at build time. The site stays static; only the source of the words changes.

But what about the dynamic parts?

This is where people assume they need a database. Usually they do not. The interactive pieces of a marketing site have lighter answers:

  • Contact forms. Post to a small serverless route that emails the submission through a provider like Resend. No table, no admin panel, no data to secure. The inbox is the database.
  • Search. Build a tiny JSON index at build time and filter it on the client, or use a hosted search service. For a few hundred pages, a build-time index is plenty.
  • Comments, reviews, analytics. These are solved problems with embeddable services. None of them require you to run a database.

The rule of thumb: if the data is read far more than it is written, and it changes on a human schedule rather than a per-request one, you do not need a runtime database to serve it.

The SEO payoff

Static rendering and SEO reinforce each other. Because the HTML is final at build time, the title, meta description, canonical URL, structured data and Open Graph tags are all present in the very first response. Crawlers never wait on client-side hydration to see your content, and they never hit a slow page that quietly hurts your rankings. If you want the deeper version of this, our Core Web Vitals checklist is the standard we ship every project against.

It pairs naturally with Next.js development: the App Router prerenders routes by default, generates your sitemap and Open Graph images at build, and lets you drop down to a server function only for the rare endpoint that genuinely needs one.

When you actually do need a database

To be fair to databases: the moment your content is per-user, written frequently, or queried in ways a flat file cannot answer, a database earns its place. A SaaS dashboard, a marketplace, a booking system, anything with accounts and state, all need real persistence. The mistake is not using a database. It is reaching for one before the product needs it, and paying the cost on a site that just serves words and images.

The takeaway

Default to static. Keep content in typed files, push the few interactive bits to small serverless routes or hosted services, and add a database the day your product genuinely becomes stateful, not a day before. You get a site that loads instantly, ranks well, and costs almost nothing to run.

Related service

Next.js Development Services

Production Next.js apps and sites, tuned for speed and search.

Learn more

Want this built right?

This is the work we do every day. Tell us what you are building and we will show you exactly how we would ship it.

hello@lazydevsagency.com