§
§ · custom web platform

Custom platforms, shaped by the domain.

A domain-first platform practice for operators building internal tools, client portals, and vertical SaaS when the off-the-shelf stack ran out. Next.js, Rails, or Django. Built around how your team actually works.

§ 01 · the build-vs-buy ledger

Most custom platform briefs are SaaS briefs in disguise.

We have turned away more custom platform briefs than we have built. Before any code, we run a build-vs-buy ledger. For roughly 70 percent of internal-tool briefs, an existing SaaS (Retool, Airtable, Monday, Zoho, HubSpot) covers 80 percent of the requirement. We name the SaaS, the 80 percent, and the 20 percent gap. If the gap is small, we recommend the SaaS and refuse the build. If the gap is genuinely bespoke and long-horizon, custom wins. Honest advice up front is the single biggest way we save clients from six-figure mistakes.

custom wins when
  • Permission model genuinely bespoke, no SaaS comes within 20 percent
  • Data entities are proprietary to the business and long-horizon
  • Platform will be used 5+ years by 50+ users daily
  • Integration surface with ERP / CRM / warehouse is non-trivial
  • Regulated industry where data sovereignty outweighs SaaS convenience
stay on SaaS when
  • ×Retool, Airtable, or Softr covers 80%+ at a fraction of the build cost
  • ×Platform will be replaced or rethought in under 2 years
  • ×User count stays under 20 and the workflow is standard CRUD
  • ×You do not have engineering bandwidth to own the platform long-term
  • ×Budget is under $60K total; SaaS + Zapier beats any custom build at that scale
§ 02 · three platform shapes

Three shapes cover ninety percent of custom briefs.

Internal tool. Client portal. Vertical SaaS. These are the three shapes we ship. Each has a distinct architecture, auth model, and success measure. Knowing which shape the brief fits is the difference between a 10-week MVP and a 40-week rebuild.

shape 01 · internal tool

For your team, by you.

Admin dashboards, ops tools, data entry platforms. Internal users only, standard auth, read-heavy workflows with periodic writes. 15 to 30 screens typical.

timeline: 8-14 weeks

shape 02 · client portal

Multi-tenant client surface.

White-label, organization-per-client, per-user permissions, usage visibility, support tickets. Often paired with existing operations or project management internally.

timeline: 12-20 weeks

shape 03 · vertical SaaS

Your own product.

Marketing site, onboarding, billing (Stripe Billing), product, API, admin. Domain-specific, for brands who discovered operating their business requires shipping the tool.

timeline: 16-28 weeks

§ 03 · the platform lattice, in motion

Sixteen modules. One shape.

A custom platform is not a feature list. It is a lattice of connected modules whose dependency graph is the architecture. The animation below is the lattice that underlies the internal-tool and client-portal shapes we ship most often.

Fig. 1 · the platform lattice · 16 modules, 18 dependencies, one shape
§ 04 · domain-first architecture

Start with the noun. Not the stack.

Every platform has a core noun: an Order, a Patient, a Shipment, a Claim, a Contract. The whole platform is dependencies around that noun. We spend week one mapping the domain model (entities, relationships, lifecycle states, events) before writing any code. The architectural decision record (ADR) that comes out of week one sets the ceiling for every shortcut a later engineer might be tempted to take.

Editorial entity-relationship diagram of a custom platform's domain model with a central ORDER box connected to eight surrounding boxes for customer, line_item, payment, shipment, refund, status_event, approval, and invoice, with relationship labels on each connecting arrow.
Fig. 1 · the core noun and its eight relations · domain-first ERD
the week-one discovery
  1. Name the core noun and its state machine
  2. Map every entity that references it (belongs_to, has_many, has_and_belongs_to_many)
  3. Write the lifecycle events the noun fires (created, approved, shipped, canceled, refunded)
  4. Map the permission model against the noun (who can view, edit, approve, delete)
  5. Identify every external system the noun syncs to (ERP, warehouse, accounting)
  6. Draft the ADR: "why we modeled it this way, and what we rejected"
§ 05 · stack decision matrix

Next.js, Rails, or Django. Pick by who runs it after us.

 Next.js + PostgresRails + PostgresDjango + Postgres
best for teamReact/TS engineersRails veterans, CRUD-heavyPython teams, data-heavy
shipping speedgoodfastest CRUDfast
admin generatorsbuild or Retool for adminActiveAdmin, AvoDjango admin (the best in class)
marketing site co-locatedyes, naturalpossible, usually separatepossible, usually separate
best fit shapeclient portal, vertical SaaSinternal tool, CRUD platformdata-heavy, ML-adjacent, regulated
§ 06 · auth + permissions

Auth is a bought commodity. Permissions are the whole platform.

We do not hand-roll authentication. Clerk, Auth0, Supabase Auth, or NextAuth with a managed OAuth provider do authentication better than any custom implementation. What we build is the permission model on top: roles, capabilities, row-level security, and the audit log that proves who changed what.

permission model
  • Capabilities (can_approve_refund, can_view_financial) mapped to roles
  • Roles mapped to users with organization or tenant scope
  • Row-level security through a tenant column on every multi-tenant table
  • Attribute-based access control (ABAC) for complex conditions
audit log
  • Every permission change logged with before, after, who, when
  • Every sensitive action (delete, export, admin change) audited
  • Audit log is append-only, separate from application DB, retained 7 years minimum
  • Queryable by compliance team without engineer intervention
§ 07 · data layer + migrations

Database migrations are first-class citizens.

The biggest difference between a platform that stays alive and one that becomes legacy is migration discipline. Every schema change goes through a migration file in the repository. Migrations are reversible. Migrations run in CI before they run in production. Production databases are never hand-edited. This single habit extends platform lifespan by years.

migration discipline · the rules
  1. Every schema change is a numbered migration file in the repo
  2. Every migration has a tested rollback path
  3. Migrations run in CI against a production-snapshot before production deploy
  4. Backfills for large tables happen in batches with progress tracking, never in a single transaction
  5. Column renames and type changes use the expand-and-contract pattern over two releases
  6. Destructive migrations (drop column, drop table) require a 30-day staging period before production
  7. Production DB is never accessed with raw SQL by humans except via audited read-only console
§ 08 · events + queues

Every meaningful action fires an event.

Platforms that ship as "request-response only" eventually hit a scaling wall where every user action blocks on downstream work (emails, webhooks, cache invalidation, analytics). We design event-driven from week one. State changes fire events. Background workers consume them via a queue. The platform stays responsive under load and integrations stay decoupled from the core.

queue 01

Transactional email.

Signup, password reset, invoice, notification. Via Resend, Postmark, or SendGrid. Retries with exponential backoff.

queue 02

Webhook delivery.

Outbound to third-party integrations. Signed, retried 5 times with backoff. Dead-letter queue for permanent failures with admin notification.

queue 03

Long-running jobs.

Report generation, data export, large backfills. Via Inngest, Sidekiq, or Celery. Progress tracked, cancelable.

§ 09 · integrations + webhooks

The platform outlives any single integration.

Every integration lives behind a dedicated service layer. Never inline in the domain logic. If Salesforce changes their API, we swap the Salesforce service class without touching the core. If the business moves from NetSuite to SAP, the migration is localized. This isolation is cheap to do up front and expensive to retrofit later.

ERP

NetSuite, SAP, Dynamics, QuickBooks, Xero, Acumatica

CRM

Salesforce, HubSpot, Pipedrive, Zoho

data warehouse

Snowflake, BigQuery, Redshift via Airbyte or Fivetran

observability

Sentry, Datadog, Logtail, PostHog for product analytics

§ 10 · proof

Two archetype platforms.

archetype 01 · logistics operator, 80 users

Internal ops platform on Rails.

Custom shipment-routing tool with real-time carrier rates, per-user permissions, NetSuite sync, audit log. Rails + Postgres + Sidekiq + Stimulus. 12 weeks from discovery to production.

users
80
daily
shipments/day
2,400
routed
ops time saved
3.8h/day
per operator
archetype 02 · healthcare-adjacent SaaS, 400 orgs

Multi-tenant client portal on Next.js.

Multi-organization client platform, per-user HIPAA-adjacent permissions, Stripe Billing, white-label per org, audit log. Next.js + Prisma + Postgres + Inngest + Clerk. 18 weeks to production.

orgs
400
active tenants
MRR
$140K
18mo post-launch
churn
3.2%
monthly
§ 11 · engagement shapes + fit

Four shapes. Discovery names the right one.

shape 01

Discovery.

2 weeks. Domain model, build-vs-buy, stack reco, ADR log. Refundable. Contact for quote.

shape 02

Internal tool MVP.

8-14 weeks. Auth, roles, 15-30 screens, integrations. Contact for quote.

shape 03

Client portal.

12-20 weeks. Multi-tenant, per-user perms, billing. Contact for quote.

shape 04

Vertical SaaS.

16-28 weeks. Marketing + product + billing + admin. Contact for quote.

right fit
  • Off-the-shelf SaaS genuinely does not fit the permission or data model
  • Platform will be used 5+ years by meaningful user volume
  • You have engineering bandwidth to maintain the platform post-handoff
  • Budget above $100K for internal tools, $250K for portals, $500K+ for SaaS
  • You want a system your team understands, not a black box
wrong fit
  • ×Retool or Airtable would cover 80% at 10% of the cost
  • ×You need it in 6 weeks; we do not compress quality
  • ×User count stays under 20 and workflow is standard CRUD
  • ×No one on your team will own the platform after we hand off
  • ×Budget under $80K; SaaS + automation will outperform any custom build
§ 12 · questions

Seven answers.

When does custom win over SaaS like Retool or Airtable?

Three conditions usually tip it to custom. First, the permission model is genuinely bespoke and no SaaS row-level security comes close. Second, the data entities are proprietary to the business (custom legal contracts, regulated healthcare workflows, industry-specific inventory) and owning the schema outweighs the SaaS convenience. Third, the platform will be used for 5+ years by 50+ users daily, making the build cost amortize cleanly. Retool wins for quick internal admin tools; Airtable wins when the team already works in tables; custom wins when neither covers the workflow and the brief is long-horizon.

What stack do you pick, and why?

Three defaults we go to most often. Next.js with TypeScript for teams already working in React and JavaScript, or for platforms that need a public marketing surface + authenticated product on one codebase. Ruby on Rails for teams valuing shipping speed, rich admin generators, and a mature ecosystem, especially when the domain is CRUD-heavy. Django for Python-native teams or for data-heavy platforms where Python libraries in the domain (scientific computing, ML, scraping) matter more than framework speed. We do not ideologically prefer one stack. We pick based on who will run the platform after we hand off.

How much does a custom web platform cost in 2026?

Platform work is quoted by scope, team composition, and domain complexity. An internal tool MVP runs 8 to 14 weeks. A multi-tenant client portal runs 12 to 20 weeks. A vertical SaaS build (marketing site plus product plus billing plus admin) runs 16 to 28 weeks. US and UK senior platform engineers are $140 to $190 per hour at boutique agencies; Indian senior engineers are $85 to $130. A 2-week discovery runs as a fixed fee and is refundable against any engagement that follows. Scoped quote in 48 hours of an intro call.

How do you handle auth and permissions?

Auth: we default to managed providers (Auth0, Clerk, Supabase Auth, or NextAuth with a managed OAuth provider). We do not hand-roll authentication for production platforms. Permissions: row-level security is the default pattern, not endpoint-level authorization. We model permissions as capabilities (can_invoice, can_approve_refund) mapped to roles, mapped to users, with row-level scoping through a tenant or organization column on every row. For platforms with complex permission matrices we add attribute-based access control (ABAC) on top. Every permission change is audit-logged.

Who owns the code, data, and infrastructure on exit?

You do, entirely. GitHub repository under your organization from day one. Infrastructure on your accounts (Vercel, AWS, Google Cloud, Cloudflare). Database in your region on your cloud. Environment variables, API keys, and third-party integrations under your billing. DH engineers get named access, removable any time. On exit: repository transferred, deployment documentation written, runbook for production incidents recorded as Loom, 30-day support tail. No vendor lock-in through code, config, or hosting.

How do you prevent the custom platform from becoming legacy?

Three habits. One, dependency versions pinned and a quarterly upgrade cadence we budget into retainer. Two, database migrations treated as first-class (forward + reverse, tested in CI, never hand-edited in production). Three, an architectural decision record (ADR) log where every significant choice is written down with context, so a future engineer (yours or ours) can understand why the code looks the way it does. Most custom platforms become legacy because the original team left and nothing was documented. We document as we go.

Do you integrate with our existing ERP, CRM, or data warehouse?

Named integrations with NetSuite, SAP, Salesforce, HubSpot, QuickBooks, Xero, Snowflake, BigQuery, and Segment. Three integration patterns cover most: webhook-based for real-time events, queue-driven for bulk syncs (Kafka, RabbitMQ, or a managed queue), and scheduled ETL via Airbyte or Fivetran for warehouse loads. We always isolate integrations behind a dedicated service layer so the core platform can outlive any single integration partner.

Start with discovery.

Two weeks. Domain model, build-vs-buy analysis, stack recommendation, ADR log. Refundable against any build that follows. Scoped quote in 48 hours.