Blog

  • What I/O Psychologists Know About AI Adoption That Engineers Miss

    My M.S. in Industrial/Organizational Psychology has proven more useful for shipping AI systems than most engineers expect, and I say that having spent 19 years at Lockheed Martin watching technically excellent tools fail because their designers never studied how human beings actually adopt new behaviors inside organizations.

    The Technology Acceptance Model Is Right and Also Insufficient

    Every I/O psychology graduate student learns the Technology Acceptance Model — Davis’s framework from 1989 that predicts adoption from two variables: perceived usefulness and perceived ease of use. TAM holds up remarkably well across four decades of research. If people don’t believe a tool will make their work better, or if they find it confusing to operate, they won’t use it. That part is correct.

    What TAM underweights — and what I watched play out repeatedly across 17 AI and automation projects — is the social and identity layer. Perceived usefulness is not calculated in isolation. It’s calculated in comparison: useful compared to what I do now, useful according to people I respect, threatening to what I’m known for being good at. The research on social influence in technology adoption has expanded substantially since Davis wrote his original paper, and the organizational behavior literature is unambiguous: your colleagues’ opinions about a tool predict your adoption of it more reliably than the documentation does.

    Two Adoption Outcomes from the Same Organization

    At Lockheed, I watched two AI-adjacent tools launch into similar finance analyst populations within the same 18-month window. The first was technically superior — better accuracy, cleaner interface, faster outputs. Adoption landed below 20% after 90 days and never recovered. The tool was positioned, implicitly through its design and explicitly through its rollout messaging, as a replacement for the judgment the analysts had spent years developing. When a senior analyst felt the tool was saying her expertise was no longer necessary, she didn’t complain loudly. She just stopped opening it.

    The second tool, which I helped design and position, reached 94% adoption within 60 days. The difference was not the algorithm. The difference was a deliberate framing decision made before a single line of code was written: the AI surfaces patterns and flags anomalies, and the analyst decides what they mean. Every interface element, every training session, every executive communication reinforced that frame. The analysts’ judgment was the point. The tool was the assistant.

    The Champion Model: Influence Nodes Before Broad Rollout

    Organizational psychology has a well-documented framework for change diffusion — Rogers’s Diffusion of Innovations — and it tells you something specific about early adopters: they are not just first users. They are influence nodes. Their opinion ripples through the social network of the team in ways that documentation and training cannot replicate.

    My practice across enterprise AI deployments is to identify three to five people who carry social credibility in the target group — not necessarily the most senior people, but the ones others ask for opinions — and get genuine buy-in from them before the general rollout. This is not manipulation. It’s recognizing that organizational adoption is a social process, not a rational calculation performed independently by each individual. If you skip this step and go straight to broad deployment, you’re hoping the math works in your favor. It often doesn’t.

    Resistance, when it comes, deserves the same interpretive generosity. When an analyst says a tool doesn’t work for her use case, she is frequently correct. The edge case she’s describing is real. Engineers who treat resistance as obstruction miss the signal — they get slower adoption and worse systems. Engineers who treat resistance as data get faster adoption and better systems.

    What Transfers

    The parallel that I find most clarifying comes from my training as a Licensed Marriage and Family Therapist. In clinical practice, the research on therapeutic outcomes is consistent: client buy-in to the treatment model must be established before behavior change begins. A technically correct intervention delivered to an ambivalent client produces worse outcomes than a slightly less refined intervention delivered to a client who understands and endorses the approach. The therapeutic alliance predicts outcomes more strongly than the specific technique.

    AI adoption follows the same structure. The quality of your model matters. The quality of your deployment relationship matters more. Teams that build organizational buy-in before broad rollout — that treat adoption as a human behavior problem rather than a communication problem — consistently outperform teams that don’t, regardless of the underlying technical quality of the system. I’ve written about the intersection of clinical training and AI systems design in more depth elsewhere, but the short version is this: the behavioral science was never separate from the engineering work. It was always the harder part.

    Building something at the intersection of AI, edge computing, and behavioral science? Let’s connect.

  • Durable Objects vs. D1: Choosing the Right State Layer for Your Cloudflare App

    I have 60 Cloudflare Workers in production and I’ve made the wrong choice between Durable Objects and D1 exactly once — it cost me two days of refactoring, which is cheap tuition for a lesson that now shapes every architectural decision I make on the edge. The confusion is understandable: both technologies persist state, both live at the edge, and both are positioned as solutions to the “stateless Worker” problem. But they solve fundamentally different problems, and choosing the wrong one doesn’t just make your code awkward — it makes your cost model and your correctness guarantees both wrong.

    What D1 Actually Is

    D1 is SQLite at the edge — a relational database you query with standard SQL, replicated globally by Cloudflare, accessed via a binding in your Worker. It behaves like a database because it is a database. You write a query, you get rows back, you have transactions, foreign keys, indexes, and all the relational primitives you’d expect. The replication model means reads can be served from the nearest replica and writes go to the primary with propagation to replicas on a short delay — which is the standard read-your-writes trade-off that any distributed database makes. D1 is the right tool for any workload that looks like a database workload: multi-tenant CRUD applications, analytics queries over structured records, any situation where you have a schema and you want to query it with SQL. In my fleet, FinRec — the personal finance PWA I built and described in detail in my post on building a finance PWA on Cloudflare Workers — runs entirely on D1. Every transaction record, every account, every budget category lives in a D1 database with a proper schema. The queries are straightforward SQL: SELECT transactions WHERE account_id = ? AND date > ? ORDER BY date DESC. D1 handles that workload with sub-10ms query times and no coordination complexity whatsoever.

    What Durable Objects Actually Are

    A Durable Object is not a database — it’s a stateful actor. A single instance of a Durable Object exists at exactly one location in Cloudflare’s network at any given time, and all requests to that object are serialized through that single instance. That serialization guarantee is the entire point: it means you can do things that are impossible with a replicated database, like maintaining an exactly-once counter, coordinating real-time state between multiple WebSocket connections, or enforcing a rate limit that is globally consistent rather than per-region consistent. The storage that a Durable Object has access to is key-value storage local to that instance — fast, strongly consistent, but not SQL, not queryable in aggregate, and not shareable across object instances. You don’t query a Durable Object the way you query D1; you send it a message and it responds, maintaining its own internal state between messages. In my fleet, the career intelligence dashboard at jobs.groundedintelligences.com uses Durable Objects for rate limiting inbound API calls — each rate limiter is a Durable Object instance keyed to a specific API client, and because all requests from that client route to the same object instance, the counter is always accurate with no race conditions. The OSINT monitoring system in my fleet uses KV for caching external feed responses and D1 for structured event storage — cert transparency log entries, threat feed matches, and alert history all go into D1 with timestamps and source metadata, making them queryable for trend analysis and auditing.

    The Key Distinction and the Cost Reality

    The cleanest mental model for choosing between them: D1 is a database you query; a Durable Object is a stateful actor you message. If your use case involves retrieving or storing structured records that multiple users or processes access independently, you want D1. If your use case involves coordinating state across concurrent requests where order and consistency matter at the request level — not just the transaction level — you want Durable Objects. The cost difference reinforces this. D1 charges per query at very low rates — roughly $0.001 per million read queries on the paid plan, with generous free tier allocations. Durable Objects charge per incoming request and per second of active duration — which means a long-running WebSocket connection or a frequently-polled coordination object accumulates duration costs that a D1 query workload never would. For short-lived stateful operations like rate limiting or session coordination, Durable Objects are cost-effective. For always-on, high-request-volume coordination, the duration billing adds up in ways that aren’t immediately obvious when you’re designing the system.

    The Mistake Most Builders Make

    The most common error I see in Cloudflare architecture discussions is reaching for Durable Objects when D1 would be correct, because Durable Objects sound more powerful and technically interesting. They are more complex — which is not the same thing as more powerful for every problem. If you need to store and retrieve user records for a SaaS application, Durable Objects give you single-instance serialization and key-value storage for a problem that just needs a relational database. You’ll end up implementing your own query layer on top of Durable Object storage, fighting the absence of joins and indexes, and paying duration costs for object instances that are essentially just holding data that D1 would serve faster. This was the mistake I made in the project that cost me two days of refactoring — I used Durable Objects for structured data storage because I was experimenting with the technology, and I spent those two days rewriting to D1 once the query requirements became clear. The technology is genuinely impressive and there are workloads it handles better than anything else — real-time collaborative editing, game state, presence systems, exactly-once processing pipelines. Those are real use cases. Storing user profile records is not one of them.

    What Transfers

    The stateful actor versus relational database distinction exists in every distributed system — this is not a Cloudflare-specific decision. Erlang has had the actor model since the 1980s. Akka brings it to the JVM. Orleans brings it to .NET. Every implementation of the actor pattern makes the same trade-off: strong per-actor consistency and message serialization, at the cost of aggregate queryability and shared state. The relational database makes the opposite trade-off: powerful query capabilities and shared state, at the cost of per-record coordination guarantees. Understanding which trade-off your workload actually requires is the architectural judgment call — and it’s easier to make clearly when you’re not choosing between two products on a pricing page but instead asking the underlying question: do I need to query this data, or do I need to coordinate around it?

    Building something at the intersection of AI, edge computing, and behavioral science? Let’s connect.

  • Deploying AI in Regulated Environments: The Five Rules That Actually Matter

    After 17 AI and automation deployments in aerospace defense finance — projects where errors had audit implications, where every business case required finance leadership sign-off, and where “the model got it wrong” was not an acceptable incident report — I have a short list of rules that the standard enterprise AI guidance omits. These are not about model selection or infrastructure. They’re about the organizational and process conditions that determine whether an AI system survives first contact with production.

    Rule One: Baseline Before You Build

    You cannot prove improvement without a baseline, and most teams skip baselining because it delays the part that feels like progress. The correct protocol is to measure the current process for four to six weeks — tracking the same metrics you plan to track post-deployment — before any model or automation is introduced. This gives you a genuine before-and-after comparison that can survive scrutiny. Without it, you have a number that represents “what the system produces” with no reference point for whether that’s better, worse, or the same as what existed before.

    Rule Two: Encode Tacit Knowledge Before Automating

    Manual processes accumulate undocumented corrections. Analysts know that certain data fields mean something different in context, that certain edge cases require a judgment call not captured in any procedure, that certain values get quietly adjusted based on experience. When you automate the process without surfacing those corrections first, the automation produces outputs that disagree with what experienced humans would produce — and the team spends weeks figuring out why the automation is “wrong” when actually the automation is correct and the tacit knowledge just wasn’t encoded. The fix is process mapping sessions before build, specifically designed to surface what people actually do versus what the procedure says they do.

    Rule Three: Design for Consequential Decisions Differently

    Not all decisions in a workflow have the same consequence profile. For a major defense aircraft program withhold tracking system, it meant mapping the consequence of each automated decision and setting a dollar threshold above which human review was mandatory — not recommended, mandatory. The model could flag, explain, and rank; a person owned the decision. This design principle — automation for volume, human judgment for consequence — is not a hedge against AI capability; it’s the correct system design for any workflow where some decisions carry disproportionate accountability.

    Rule Four: Measure What the Model Gets Wrong, Not Just What It Gets Right

    Accuracy metrics that report overall performance obscure the distribution of errors. A model with 94% accuracy that fails catastrophically on a specific class of inputs may be worse than a model with 89% overall accuracy that fails more evenly. In the internal tax scenario classifier — the tax scenario processing system — we tracked error rate by category, not just overall. Some categories had error rates below 2%; others had rates above 12%. The overall accuracy number looked good; the category breakdown told us where the model couldn’t be trusted, which is the information that actually shapes how you deploy it.

    Rule Five: Write the Control Plan Before You Launch

    A deployed model without a control plan is a model with an unknown expiration date. The control plan needs to specify: which metrics indicate the model is within acceptable performance bounds, what threshold triggers a retraining evaluation, who owns the retraining decision, and what the rollback procedure is if a retrained version performs worse than its predecessor. These are not governance overhead — they’re what separates a system that maintains its accuracy over time from one that quietly degrades until someone notices the outputs are wrong.

    What Transfers

    None of these rules are specific to aerospace or defense. They apply to any organization deploying AI in a context where errors have real consequences — financial, legal, operational, or reputational. The regulated environment makes the requirements explicit; in less regulated contexts, the requirements still exist, they’re just easier to ignore until something breaks.

    Building something at the intersection of AI, edge computing, and behavioral science? Let’s connect.

  • When AI Meets FP&A: Lessons from Automating Defense Finance

    The 2,132 hours per year figure is not an estimate. It came from a three-week manual time study conducted before any automation existed, where analysts logged their work against specific task categories while the baseline process ran unchanged. That number — and the $360,000+ in annual cost avoidance it represents — survived finance leadership scrutiny because the methodology was designed to be auditable before the first line of code was written.

    What the Problem Actually Was

    Defense program finance involves tracking a multi-hundred-million-dollar contract financial position tied to a major defense aircraft program — “withholds” being the portion of payments held back pending milestone, quality, or compliance conditions being met. Managing that position manually meant analysts reconciling data across multiple systems, building the same variance tables repeatedly, and spending a disproportionate share of their time on data assembly rather than analysis. The work wasn’t intellectually complex; it was procedurally complicated and time-consuming. That combination — low cognitive load, high time cost, clear rules — is exactly where automation performs well. The error rate in manual reconciliation was also meaningful: human error in a data assembly task with dozens of interdependent fields is not a character flaw; it’s a system design problem. Automating the assembly eliminates a category of error rather than reducing it incrementally.

    The Build: What Went In and What Didn’t

    The automation stack was Alteryx for data pipeline orchestration and Python for the more complex analytical components. Alteryx handled the extraction, transformation, and loading work: pulling from multiple source systems, applying business rules for categorization, and producing reconciled outputs. Python handled the variance detection logic — specifically, flagging variances that exceeded threshold values and generating the explanatory text that would previously require an analyst to write from scratch each cycle. What didn’t go into the automation: judgment calls. Variances above a certain dollar threshold still required an analyst to review the flag, understand the context, and decide whether escalation was warranted. Automating the detection is appropriate. Automating the decision is not, in a financial position with audit implications. The system was designed to produce recommendations, not approvals.

    What Went Wrong First

    The first version of the data pipeline produced reconciliation outputs that didn’t match the manual outputs analysts had been generating. Not because the logic was wrong — the logic was correct — but because the source data had inconsistencies that the manual process had been silently correcting through analyst judgment. Analysts knew that certain fields needed to be interpreted in context, not taken at face value, and they applied that interpretation automatically without documenting it. The automation exposed those undocumented corrections and made them explicit. The fix required going back to the analysts, documenting every correction they were making, and encoding that logic into the pipeline. This added three weeks to the build timeline and was entirely predictable if we had done more thorough process mapping upfront. The lesson isn’t that analysts were hiding things; it’s that tacit knowledge embedded in manual processes doesn’t surface until you try to replace the process with rules.

    Measuring the Outcome

    The 2,132 hours per year was calculated by comparing post-automation task logs against the pre-automation baseline, controlling for volume changes in the underlying program activity. The $360,000 figure used fully loaded labor rates — not salary alone — applied to the recovered hours, minus annual system maintenance costs and a periodic retraining allocation. The number presented to finance leadership was lower than the first draft, which made it more credible precisely because it showed the methodology rather than optimizing for the largest possible figure. Sensitivity analysis was prepared in advance: if the loaded labor rate assumption was adjusted down by 15%, the cost avoidance figure fell to $305,000. Finance could stress-test the assumption and the number still held.

    What Transfers

    Every element of this project — the time study methodology, the explicit encoding of tacit process knowledge, the threshold-based human review design, the auditable ROI methodology — transfers directly to enterprise AI work in any domain with similar characteristics: high-volume, rule-governed data tasks with meaningful error costs and financial accountability requirements. The aerospace context made the stakes and the review process more formal, but the discipline is domain-agnostic.

    Building something at the intersection of AI, edge computing, and behavioral science? Let’s connect.

  • LLM Evaluation at Scale: Building a Golden Dataset That Actually Works

    I have watched teams ship LLM features with no structured evaluation whatsoever — no golden dataset, no inter-rater agreement calculation, no adversarial examples — and then express genuine surprise three weeks later when production breaks in ways that dev never predicted. This is not a tooling problem or a research problem; it’s a discipline problem, and the fix is unglamorous: you need a curated, annotated evaluation set built before you ship, not assembled in a panic after your first production incident.

    What a Golden Dataset Actually Is

    A golden dataset is a curated collection of (input, expected_output) pairs that represent the real distribution of tasks your model will encounter in production — including the hard ones, the edge cases, and the inputs specifically designed to surface failure modes. It is not a sample of the easy inputs where the model already performs well. It is not a set of examples you grabbed from a tutorial. It is a structured artifact, maintained like code, that tells you whether your model is getting better or worse as you iterate. Three ingredients separate a real golden dataset from a list of test cases someone threw together on a Friday afternoon. First, it needs at least 500 examples — below that threshold, your accuracy measurements have confidence intervals wide enough to be meaningless. Second, it needs adversarial examples mixed with the easy ones in a ratio that reflects your actual production failure rate — if 15% of your production inputs are edge cases, your golden set should be at least 15% adversarial. Third, every example needs to be annotated by at least two independent annotators, with inter-rater reliability calculated using Cohen’s kappa — and your target kappa should be 0.7 or higher before you trust the labels.

    How the internal tax scenario classifier Forced the Discipline

    When I built the internal tax scenario classifier — the tax scenario processing system that ran 415,000 scenarios in 4 hours and achieved a 31% reduction in purchase order error rate — the evaluation problem was not optional. Tax classification is high-stakes and adversarially complex: the same economic transaction can have materially different tax treatments depending on jurisdiction, contract structure, and a half-dozen other variables. Getting the model wrong didn’t produce a slightly inconvenient user experience; it produced incorrect tax filings with audit exposure attached. We built an annotation corpus of 8,000+ labeled tax scenarios before we ran a single evaluation pass. The annotation workflow ran in three phases: a senior tax specialist assigned the ground-truth label for each scenario, a second specialist reviewed independently, and disagreements went to a structured resolution process where both annotators discussed the case against a written decision criteria document before a label was assigned. The kappa score in the first annotation round was 0.61 — below the 0.7 threshold — which told us the labeling criteria were ambiguous in about 20% of the cases. We spent two weeks tightening the criteria document and re-annotating the contested examples. The second pass came in at 0.74. That kappa score meant something: when the model scored 88% accuracy against that dataset, we had high confidence the 88% was real and not an artifact of easy examples and loose labels.

    The Distribution Trap

    The most common mistake teams make after building a golden dataset is constructing one that is too easy — heavy on the clear-cut cases, light on the ambiguous ones — and then celebrating when the model hits 94% accuracy. That number is meaningless if your production inputs include the 6% of scenarios where the model catastrophically fails, because that 6% might represent the highest-stakes decisions in the entire workflow. The adversarial examples you add in week three of evaluation should not be random stress tests — they should be the actual failure modes you observed when you let the model run on unlabeled production data in shadow mode. Shadow mode evaluation — running the model in parallel with the existing process without using its outputs, just observing — is how you discover what your golden set is missing. The failure modes you find in shadow mode become your adversarial examples, which makes your golden set a living artifact that improves as you learn more about where the model breaks.

    What Transfers

    Clinical assessment methodology has required structured reliability measurement for decades — the DSM field trials that established diagnostic criteria used inter-rater kappa as a primary validity metric, and a diagnostic tool with kappa below 0.8 was considered insufficiently reliable for clinical use. That standard didn’t emerge because psychologists are unusually rigorous; it emerged because the cost of diagnostic error — misdiagnosis, missed treatment, wrong intervention — made reliability non-negotiable. LLM evaluation should be held to the same logic. If the model’s output touches a consequential decision, the annotation process that produces your ground truth needs enough rigor that two independent experts agree on the right answer at least 70% of the time after accounting for chance agreement. Below that threshold, you’re not measuring model performance — you’re measuring label noise. The investment in evaluation infrastructure is front-loaded and genuinely tedious, but it’s the only thing that gives you honest signal about whether your model is improving or whether you’re just iterating on vibes.

    Building something at the intersection of AI, edge computing, and behavioral science? Let’s connect.

  • The Behavioral Science Argument for Explainable AI

    As a Licensed Marriage and Family Therapist who spent 19 years building AI systems inside a defense contractor, I can tell you that the most dangerous assumption in AI explainability design is the belief that showing people more information makes them understand better. It doesn’t — and the cognitive science has been clear on this for decades. Humans don’t form beliefs by evaluating evidence and then reaching conclusions; they reach conclusions first, usually within seconds, and then work backward to construct a rationale that justifies what they already decided. Post-hoc rationalization isn’t a flaw in a few people — it’s the default operating mode of the human mind.

    Why “Just Show the Model Output” Fails

    The standard approach to AI transparency is to surface the output with some kind of confidence score or feature attribution attached. The implicit theory is: if users can see why the model decided what it decided, they’ll calibrate their trust appropriately. The problem is that people don’t use explanations to calibrate trust — they use them to confirm the conclusion they already formed. If the model output looks plausible, they rationalize the explanation as supporting it. If the output looks wrong, they rationalize the explanation as evidence of model failure. The explanation becomes post-hoc justification for whatever the user already believed, which means it’s doing exactly zero calibration work. This is not a theory — it’s what happens in practice, and it’s what I watched happen in clinical settings long before I was building AI systems. Patients who received detailed diagnoses with extensive supporting evidence were not more compliant than patients who received clear, direct recommendations in their own language. In fact, they were sometimes less compliant, because more information gave them more material to selectively interpret.

    The Two Failure Modes from I/O Psychology

    Industrial/Organizational psychology names two failure modes that show up in every AI deployment I’ve worked on. The first is automation bias — users trust the AI output even when it is clearly wrong, because the system has established a track record of being right and the user’s vigilance erodes over time. The second is algorithm aversion — users reject AI output even when it is clearly right, because a visible failure early in the deployment destroyed their confidence and they never rebuilt it. Both failure modes are trust calibration problems, and neither one is solved by adding more explanation text to the interface. Automation bias gets worse when the explanations sound authoritative, because authoritative-sounding text reinforces rather than disrupts overconfidence. Algorithm aversion gets worse when explanations expose model uncertainty — if a user who already distrusts the system sees “confidence: 61%” attached to a prediction, that number confirms their suspicion that the model doesn’t really know what it’s doing.

    What Actually Works: Domain Language, Not Model Language

    The principle that transfers from clinical practice to AI explainability is this: speak the patient’s language, not the diagnostic manual’s language. A therapist who explains a diagnosis using DSM-5 criteria loses the patient in the first 30 seconds. A therapist who says “this looks like the same pattern we saw last spring, when work stress was highest and sleep dropped below six hours” keeps the patient engaged because the explanation is constructed from their own experience. The same principle applies to AI explanations — but almost no one applies it. At Lockheed, the early version of our variance detection system surfaced explanations using model terminology: anomaly scores, deviation coefficients, feature weights. The finance analysts looked at those explanations, nodded, and then completely ignored the model outputs within three weeks. After we rebuilt the explanation layer to use their domain language — “this cost line exceeded the 3-year program average by $142,000, which is outside the normal range for this phase of production” — adoption recovered and stayed above 80% for the rest of the program. Nothing in the model changed. Only the explanation framing changed. That’s the behavioral science argument for explainable AI: the explanation is a communication design problem, not a technical transparency problem. You can read more about how that kind of thinking applies across my enterprise AI work in my post on deploying AI in regulated environments.

    What Transfers

    Clinical communication training teaches one thing above everything else: you cannot inform someone into a different belief — you have to meet them inside the belief system they already have and build from there. That’s not manipulation; it’s the actual mechanism by which understanding happens. An AI explanation that says “SHAP value = 0.73 for feature: cost_variance” is not communicating anything to a finance analyst. An explanation that says “this decision looks different from your last 12 similar decisions” is communicating something real, in a frame the user can act on. The lesson extends beyond AI — any system that asks humans to change their behavior based on algorithmic output needs to be designed around how trust is actually built and maintained in human cognition, not around how transparency is theoretically supposed to work. If you’re building AI systems that touch consequential decisions and you haven’t read the automation bias literature, that’s the first gap worth closing. If you want to understand more about why I approach AI from a behavioral science foundation, that’s exactly what I wrote about in this post on why a therapist builds AI systems.

    Building something at the intersection of AI, edge computing, and behavioral science? Let’s connect.

  • How I Built and Run a 60-Worker Cloudflare Fleet on $0/Month

    I run 60 production Cloudflare Workers for $0 per month — the only thing I pay is roughly $12 a year for a domain name. That’s not a development environment or a hobby experiment; that’s a fleet of real applications handling authentication, SQL queries, OSINT monitoring, AI inference, and job-matching logic, all running at the edge with no servers to manage and no cloud bill showing up at the end of the month.

    What the Free Tier Actually Gives You

    Cloudflare’s free tier is generous in ways that most people don’t fully appreciate until they map their workloads against the actual limits. Each Worker gets 100,000 requests per day — not per account, per worker — before you hit any throttle. D1, Cloudflare’s SQLite-at-the-edge product, gives you 5GB of storage and 25 million reads per day at no cost. KV gives you 100,000 reads per day. R2 gives you 10GB of object storage, 1 million Class A operations, and 10 million Class B operations monthly. Workers AI gives you 10,000 neurons per day on the free plan — enough to run real inference tasks at modest volume. Stack those together and you have a full-stack compute and storage platform that would run $200 to $400 a month on AWS if you tried to replicate it with Lambda, RDS, ElastiCache, and S3.

    The Architecture That Makes It Work

    The design principle behind the fleet is stateless compute paired with durable storage — the Worker itself holds no state between requests, which means cold starts are measured in microseconds rather than seconds, and horizontal scaling is automatic. Workers handle request routing, business logic, authentication, and API composition. D1 handles anything that needs relational structure and SQL queries. KV handles read-heavy caching where eventual consistency is acceptable — configuration values, session tokens, rate-limit counters. R2 holds files, exports, and anything that would otherwise require a file system. Workers AI sits at the inference layer, running models like LLaMA 3 without me spinning up a GPU instance. The whole architecture collapses the traditional web stack into a single deploy surface with one CLI command.

    Three Workers That Show the Range

    FinRec is my personal finance PWA — it runs entirely on Workers and D1, with a React front end served from Workers’ static asset hosting and a SQL backend running on D1. Every transaction, category, and account record lives in a D1 database. I wrote about the full build process in detail in this post on building FinRec. The application handles multi-user data with row-level scoping in SQL, processes hundreds of transactions without latency issues, and costs nothing beyond the domain. Digital Sentinel is my OSINT monitoring system — it uses Cron Triggers to run scheduled jobs every 15 minutes, polling certificate transparency logs and threat intelligence feeds, then routing alerts to a Discord webhook when it finds something worth flagging. There’s no always-on server; the Cron Trigger fires the Worker on schedule, the Worker runs its checks, and then it’s gone until the next cycle. I covered the full architecture in my post on building the OSINT monitoring system. The third is daniel-job-search, the career intelligence dashboard running at jobs.groundedintelligences.com — it uses Workers AI to run job-matching inference against my criteria, scoring inbound postings and surfacing the highest-signal opportunities. The AI layer runs on LLaMA 3 via Workers AI, the results are stored in D1, and the front end is a PWA served from the same Worker.

    The Deployment Workflow

    Every worker in the fleet deploys from a wrangler.toml file that specifies the worker name, the account ID, any KV namespace bindings, D1 database bindings, and R2 bucket bindings. Wrangler CLI handles the rest — one command, wrangler deploy, pushes the compiled Worker to Cloudflare’s edge network and it’s live globally within about 15 seconds. There’s no container to build, no cluster to update, no load balancer to reconfigure. The development loop is tight: wrangler dev runs a local emulator that mirrors the production environment closely enough that production surprises are rare. When I need to rotate a secret, wrangler secret put writes it to Cloudflare’s secret store without it ever appearing in my codebase or environment files. Across 60 workers, this workflow stays manageable because each worker is a small, focused piece of logic — nothing in the fleet exceeds about 400 lines of TypeScript.

    What Transfers

    The architecture principles here are not Cloudflare-specific — they’re the underlying logic of serverless-first design applied to any provider. Stateless compute paired with durable storage is a pattern that works on AWS Lambda with DynamoDB, on Fastly Compute with Upstash, or on any platform that separates the execution layer from the persistence layer. The key insight is that infrastructure ownership is the most expensive part of running software — not in dollar terms, but in cognitive overhead, operational burden, and the time you spend keeping things running instead of building. When you design systems where you own the code and the platform owns the infrastructure, you get back the mental bandwidth to actually work on the problem. The $0/month bill is a side effect of that design choice, not the goal. The goal is a system that does real work, stays maintainable, and doesn’t require a 2 AM pager rotation to keep alive.

    Where the $0 fleet stops working: media

    The one workload this architecture will not absorb is media at volume. Cloudflare explicitly prohibits streaming video on Free, Pro and Business plans — you are expected to move to Cloudflare Stream or Enterprise — and once you are storing tens of gigabytes and serving them repeatedly, the free tier stops being the right answer regardless of how the compute is structured.

    I recently split a media pipeline along exactly this line: the control plane — D1 index, Workers AI tagging, the ranking API — stayed on Cloudflare, and the data plane — 41 GB of originals, rendered variants and video — moved to bunny.net. Storage runs about $0.01–$0.02/GB and bandwidth $0.005/GB in North America and Europe, with no free tier to age out of and no per-plan content restrictions to trip over. The interesting part is that the split is architecturally cleaner than the monolith was: metadata and logic in one place, bytes in another, and the boundary is a signed URL.

    The bunny.net link above is an affiliate link — I earn a commission if you sign up, at no additional cost to you. I pay for the service myself and would recommend it regardless.

    Building something at the intersection of AI, edge computing, and behavioral science? Let’s connect.

  • Building an OSINT Monitoring System on the Edge with Cloudflare Workers

    Building an OSINT Monitoring System on the Edge with Cloudflare Workers

    One of the less visible but most practical systems in my Cloudflare Workers fleet is Digital Sentinel — a set of OSINT (Open Source Intelligence) monitoring pipelines that scan certificate transparency logs, threat intelligence feeds, and domain registration activity, then fire automated chat alerts when something interesting shows up.

    What It Monitors

    The system pulls from multiple sources: certificate-transparency logs (catching new SSL certificates issued for domains I care about), threat-intelligence feeds for SEO and competitive-intelligence signals, URL-analysis services for malicious-URL detection, and additional threat-intelligence feeds for enrichment. Each source has its own dedicated Worker that runs on a cron schedule, queries the API, diffs against the last known state in D1, and posts alerts for anything new.

    The Architecture Pattern

    Each monitoring pipeline follows the same pattern: a cron-triggered Worker fetches data from an external API, compares it against a D1 table of previously seen items (deduplication by hash), persists new items, and sends a formatted automated chat alert for anything that crosses a threshold. The pattern is simple enough to replicate for any data source in about 30 minutes.

    What makes this interesting as an engineering exercise is the constraint set. Cloudflare Workers have a 30-second execution limit on cron triggers, so the pipelines have to be efficient — no long-running batch jobs, no streaming connections. D1’s SQLite engine handles the state management cleanly, and the Workers runtime’s built-in fetch makes external API calls trivial.

    Why This Matters

    For personal security monitoring, this system provides continuous visibility into certificate issuance, domain impersonation attempts, and threat-intel signals that would otherwise require a paid SIEM or manual checking. For my portfolio, it demonstrates the ability to build event-driven monitoring systems on modern edge infrastructure — the same pattern that scales to enterprise OSINT, brand protection, and security operations.

    The full system runs alongside 60+ other Workers in my Cloudflare fleet, all orchestrated by a meta-orchestrator that monitors the health of the entire platform and self-heals when individual Workers encounter issues.

    See more on my Projects page, or get in touch to discuss edge-native monitoring architectures.

  • Why a Therapist Builds AI Systems: The Case for Behavioral Science in Responsible AI

    Why a Therapist Builds AI Systems: The Case for Behavioral Science in Responsible AI

    When people learn I’m both a Licensed Marriage and Family Therapist and a data scientist who builds LLM evaluation pipelines, the first question is usually some version of “How did that happen?” The honest answer: the combination wasn’t an accident. It’s the product.

    The I/O Psychology Bridge

    My M.S. in Industrial/Organizational Psychology sits exactly at the intersection of behavioral science and organizational analytics. I/O Psych is about understanding how people behave in systems — how incentive structures shape decisions, how cognitive biases lead to systematic errors, how group dynamics amplify or suppress signal. These are the same problems that show up in AI alignment, fairness evaluation, and responsible AI governance.

    When I evaluate an LLM for hallucination, I’m applying the same epistemological rigor I use in clinical assessment — checking whether the system’s output is grounded in reality, identifying the conditions under which it fails, and designing interventions that make the failure visible before it causes harm.

    Why This Matters for AI

    Most data scientists who work on responsible AI come from either a pure engineering background (strong on implementation, weaker on the behavioral theory) or a policy background (strong on frameworks, weaker on production systems). Very few have clinical training — the kind where you learn to assess risk in real time, manage ambiguity in high-stakes situations, and design interventions that actually change behavior.

    My clinical license means I can speak credibly to behavioral AI ethics, human-centered transparency documentation, and fairness frameworks in a way that most engineers can’t. And my 20 years at Lockheed Martin mean I can actually ship those frameworks in production environments where getting it wrong has financial and regulatory consequences.

    The Roles Where This Wins

    The combination creates a genuine differentiator for a specific set of roles: responsible AI governance, trust & safety, behavioral-health technology (where clinical credibility opens doors that engineering credentials alone don’t), and any AI leadership position where the human side of the equation matters as much as the technical side.

    The future of AI isn’t just about making models more capable. It’s about making them trustworthy. And trustworthiness requires understanding both the system and the humans who use it.

    I hold four degrees: M.A. Counseling Psychology, M.S. Industrial/Organizational Psychology, B.S. Corporate Finance, and B.S. Business Management. More on my About page.

  • Deploying AI in Regulated Environments: Lessons from 17+ Enterprise Projects

    Deploying AI in Regulated Environments: Lessons from 17+ Enterprise Projects

    I’ve spent 19 years at Lockheed Martin. For the last four of those, I’ve led a 17+ project portfolio of automation, AI/ML, and dashboarding solutions in Aeronautics’ Finance & Business Operations Digital Transformation organization. Here are the patterns I’ve learned about deploying AI in environments where getting it wrong has real consequences.

    The Regulated-Environment Tax

    In defense, you can’t ship a model and iterate based on user complaints. The compliance surface is enormous — DCMA, DFAS, EVMS, FAR/DFAR, SOX-adjacent controls. Every automation I build has to survive not just technical review but audit scrutiny. This means the evaluation methodology, the guardrails, and the audit-logging are as important as the model itself.

    When I deployed an enterprise RAG pipeline for financial data classification, half the engineering effort went into the transparency artifacts — making sure every classification decision was traceable, every confidence score was logged, and every edge case had a human-review fallback.

    The Production Withholds Story

    The project that best illustrates this is a production withholds automation for a major defense program. The challenge: leadership needed visibility into a nine-figure withhold balance, but the source data was paragraph-form free text — inconsistent formatting, typos, abbreviations, no structured fields. The solution was a 356-tool Alteryx workflow combining ML/NLP text mining with structured field extraction, feeding a Tableau executive dashboard.

    The result: 2,132 labor hours saved per year, low-six-figure losses prevented, and the dashboard is now embedded in the program’s normal business rhythm. But the real lesson was that the NLP component had to be evaluated specifically for extraction accuracy against ground truth — not just general text classification metrics. In regulated environments, the eval framework is the product.

    AI at Scale

    More recently, I co-led an AI-driven tax-classification initiative — a cross-business-area AI chatbot evaluated against 415,000 tax scenarios on an internal enterprise AI platform. The target is a 31% reduction in purchase-order error rates. What made this different from a typical chatbot project was the evaluation rigor: structured behavior tests, accuracy validation against ground-truth tax determinations, and benchmark datasets that stress-test edge cases.

    What Transfers

    The patterns that work in defense AI transfer directly to any domain where trust matters: financial services, healthcare, legal tech, and especially responsible AI governance. Build the eval framework first. Log everything. Design for auditability from day one. And never ship a model without a human-review fallback for the cases you know it will get wrong.

    I’m currently exploring senior data scientist and AI/ML engineering roles where this kind of production rigor is valued. Get in touch.