Blog
Guides, comparisons, and engineering deep-dives from building smplkit — the decisions, tradeoffs, and how-tos behind a multi-product developer platform.
Which job schedulers fire on time? We measured ten.
Ten job schedulers, one endpoint, a POST at the top of every hour: a live benchmark of how many milliseconds late AWS EventBridge, Cloudflare Workers, cron-job.org, EasyCron, GitHub Actions, Google...
Why I built smplmark.org
smplmark.org hosts live, continuously updating benchmarks that anyone can publish under a verified name. The reasoning behind it, and behind its first benchmark: job scheduler latency.
Configuration should be live by default
Live configuration in Python — resolve() snapshots vs subscribe() proxies over WebSocket, typed Pydantic config models, and an on_change decorator.
How the logging SDK discovers every logger without you listing them
How a logging SDK auto-discovers every logger by hooking Python logging.getLogger, with framework adapters for Loguru, Winston, slf4j, and remote level control.
Evaluating a feature flag should not be a network call
Feature flag local evaluation with zero network calls per check — an SDK architecture using WebSocket live updates, lazy initialization, and context objects.
Building a document database on top of PostgreSQL
Postgres as a document database, built on a single JSONB table with a GIN index, implicit collections, equality-only containment queries, and schema-on-read.
The best cron job services for 2026: an honest comparison
An honest comparison of the best cron job services for 2026 — AWS EventBridge, Cloudflare Workers Cron, GitHub Actions, Google Cloud Scheduler, Vercel Cron, cron-job.org, EasyCron, Posthook, Runhoo...
Keeping Stripe out of your product services
Stripe subscription architecture for microservices — per-product subscription rows, bundle fan-out, and entitlement logic centralized in one shared catalog module.
The products we decided not to build
Why a multi-product platform serves its product catalog as an API — the data model, the coming-soon notify-me demand signal, and the products we cut and why.
Python coding standards for three AI agents and a human
Python coding standards for a multi-service codebase — modern type hints, Google docstrings, a shared exception hierarchy, and naming rules for AI-assisted teams.
End-to-end testing a multi-language SDK platform
End-to-end testing SDKs in multiple languages — a pytest harness shelling out to per-language scripts against a live API, and three bugs it caught on first run.
What happens to your data when you delete your account
Soft delete vs hard delete for multi-tenant SaaS account deletion — cascade soft-delete in one transaction, preserved user records, and lazy cross-service cleanup.
Why we chose ECS Fargate over Kubernetes
ECS Fargate vs Kubernetes for a small team — why we skipped the $73/month EKS control plane and NAT gateway costs, with the tradeoffs and revisit triggers.
Flat keys, real inheritance: how Smpl Config works
Why flat dot-notation configuration keys beat deep merge — explicit parent inheritance, per-environment overrides, and typed keys with descriptions in Smpl Config.
Real-time log level control without touching your code
Change log levels in production without a redeploy using logger auto-discovery via monkey-patching, a five-stage resolution hierarchy, and WebSocket level updates.
Designing a feature flag system that catches your typos
Feature flag system design with JSON Logic targeting rules, constrained vs unconstrained flag types, a single-table JSONB data model, and per-environment state.
Why we commit generated code to our SDK repos
Why we commit OpenAPI-generated SDK code, the two-layer generated-plus-wrapper client architecture, and using the Python SDK as the reference for six languages.
Shared code without a monorepo: how we built smplkit-core
Sharing Python code between microservices without a monorepo — publishing smplkit-core to AWS CodeArtifact, versioning policy, and a no-editable-installs rule.
How we prevent tenants from seeing each other's data without thinking about it
Multi-tenant API isolation with 404 not 403 — implicit account scoping from the JWT, ORM-layer filtering, and PostgreSQL row-level security to prevent IDOR/BOLA.
Why we ditched Next.js for our developer console
Why we migrated a Next.js static-export console to Vite and React Router — dynamic route workarounds, a CloudFront 404 bug, and the feature audit that settled it.
JSON:API — why we picked a standard instead of rolling our own
JSON:API vs a custom response format — why adopting the standard beat rolling our own, with PUT-only updates, 400 over 422 validation errors, and an actions pattern.
Schema conventions that let AI agents write correct code
Database schema conventions for AI coding agents — singular table names, snake_case, TEXT over VARCHAR, UUID keys, and standard columns that cut correction cycles.
Why Alembic over Liquibase for a Python FastAPI stack
Alembic vs Liquibase for a Python FastAPI and SQLAlchemy stack — autogenerate from models, Python data migrations, migrate-on-startup with a Postgres advisory lock.
Designing API key auth for a multi-product developer platform
API key design for a developer platform — account-scoped API keys vs environment-scoped SDK keys, why opaque keys beat JWTs, and 60-second introspection caching.
Why we chose PostgreSQL over DynamoDB for a multi-cloud SaaS platform
PostgreSQL vs DynamoDB for a multi-cloud SaaS — why MongoDB API compatibility on DocumentDB and CosmosDB falls short, and how JSONB replaces a document database.
Replacing Redoc with Scalar: lessons in API documentation UX
Redoc vs Scalar for API docs — why embedding Redoc in a dark-theme VitePress site failed, and how Scalar CSS variables and built-in Try It testing fixed it.
Building a consistent icon system for a product suite
Designing a consistent SVG icon system for a multi-product suite, with monochrome stroke icons, shared geometry rules, 20px legibility testing, CSS color control.
Email capture for static sites without a backend
Email capture on a static site with no backend — why Formspree beat Mailchimp, Netlify Forms, Google Forms, and a DIY Lambda stack for pre-launch signups.
Naming a developer tool: why lowercase won
How to name a developer tool — why lowercase names like smplkit win in terminals and imports, the Smpl product-family prefix, and the naming patterns we rejected.
Information architecture for a multi-product SaaS platform
Information architecture for a multi-product SaaS website — dedicated product pages vs one catalog page, coming-soon badges, and a nav flyout for fifteen products.
AWS Amplify vs S3 + CloudFront for a static marketing site
AWS Amplify vs S3 and CloudFront for a static marketing site — what the DIY stack costs to set up, why Amplify won, when Netlify or Vercel make sense, and why docs live on their own subdomain.
No posts match your filters.