Selling Digital Products Without Platforms’ Arbitrary Approval

The Problem We Were Actually Solving

Our team focused on creating an inclusive marketplace for creators and buyers alike. We ensured our digital products were accessible across the globe, with multiple payment options to accommodate different regions. However, our reliance on traditional payment gateways and e-commerce platforms made it difficult to bypass their KYC requirements. This meant we had to implement these stringent checks, which often led to friction and frustration for our customers, particularly from areas with restrictive financial regulations.

What We Tried First (And Why It Failed)

Initially, we tried integration with major payment processors like Stripe and PayPal. These integrations worked seamlessly for customers from developed economies but failed for those in emerging markets. Their restrictive policies and strict KYC requirements caused significant delays and even denied payment processing for legitimate customers. These issues added latency to our pipeline, taking an average of 5-7 minutes to resolve per transaction. Furthermore, these payment processors came with high query costs on our warehouse, resulting in an average cost of $0.25 per query. Our query cost became unsustainable with the increasing volume of denied payments, eventually hitting our 5-second query freshness SLA.

The Architecture Decision

We decided to opt for alternative payment methods that did not rely on traditional payment gatekeepers. We chose a decentralized payment system that allowed our customers to make payments via cryptocurrencies, bypassing the stringent KYC requirements. This decision allowed us to onboard customers from any region without needing to obtain approval from intermediaries. We built our solution around the Cosmos SDK, utilizing its Inter-Blockchain Communication (IBC) protocol for seamless payment processing.

What The Numbers Said After

After implementing our new payment system, our pipeline latency reduced to under 1 second, and the number of denied payments plummeted. With our new system, we experienced an average cost of $0.05 per query on our warehouse, significantly reducing our query costs. Our query freshness SLA of 5 seconds was easily met, with an average freshness of 2 seconds. Most importantly, our customers from restrictive regions were finally able to access and purchase our digital products seamlessly.

What I Would Do Differently

While our decision to opt for decentralized payment methods was successful, I would consider implementing additional measures to ensure data quality at the ingestion boundary. By adding data validation and quality checks during payment processing, we could have potentially avoided some of the errors caused by incorrect customer information. For instance, implementing a more comprehensive address validation system could have prevented instances where payments were declined due to address discrepancies.

Virtualize Game Development with NVIDIA RTX PRO 6000 Blackwell Servers

The game development ecosystem is scaling at an unprecedented rate. Modern studio teams are engineering massive, interconnected virtual worlds operating across highly complex asset pipelines, shifting rapidly toward heavily distributed remote workforces.

Despite these advanced structural transitions, a significant portion of global game studios continue to anchor their production infrastructure to fixed, desk-bound hardware workstations situated directly under local office tables.

This decentralized architecture creates severe operational inefficiencies. Million-dollar corporate graphics assets sit completely idle during overnight hours, while remote engineers across separate time zones suffer from severe processing bottlenecks. Resolving this friction mandates migrating away from desktop sprawl toward centralized server architectures.

However, deploying virtual workstations requires stripping away vendor marketing illusions and confronting brutal engineering realities regarding memory mathematics, licensing taxes, compute noise parameters, and physical distance limitations.

Corporate Intellectual Property Security Threat

Virtualizing game development requires strict network discipline. If your central server graphics provisioning interface connects directly to the public internet, malicious actors can hijack active rendering sessions—stealing unreleased game assets and proprietary engine source code directly from memory.

Site Reliability Engineers must enforce rigorous management network isolation, mandating secure tunneling protocols and multi-factor authentication (MFA) gateways before permitting remote developers to access the graphics environment.

The 48-User VRAM Marketing Illusion

Hardware vendors frequently market the 96GB NVIDIA RTX PRO 6000 Blackwell Server Edition as capable of supporting up to 48 concurrent virtual developers. For professional 3D game development, this calculation is an absolute technical fallacy.

Dividing 96GB across 48 users leaves precisely 2GB of video memory (VRAM) per session. Modern development platforms like Unreal Engine 5 require an absolute minimum of 12 to 16 Gigabytes merely to launch a blank project without triggering fatal out-of-memory software exceptions. Realistically, a single Blackwell rendering server optimally supports a maximum of 6 to 8 elite artists engineering massive, high-fidelity geometric scenes.

The Broadcom License Tax and Open Source Salvation

To centralize studio hardware resources safely, many traditional systems architects advocate for deploying proprietary virtualization stacks. While migrating away from public clouds successfully eliminates catastrophic data egress network charges, implementing corporate hypervisors introduces an equally hazardous financial trap: the massive Broadcom software subscription tax. Proprietary virtual desktop infrastructures (VDI) demand aggressive annual renewal fees per activated user profile, completely destroying your infrastructure return on investment (ROI) projections.

Modern enterprise SREs avoid this corporate tax trap by anchoring their graphics clusters entirely on open-source hypervisor architectures. Deploying your server using Proxmox VE (KVM) or integrating bare-metal clusters with Red Hat OpenShift (KubeVirt) delivers raw, uninhibited access to physical graphics compute paths. This open-source framework unlocks advanced graphics execution capabilities and coordinates user profiles flawlessly without forcing your business into expensive, multi-year software licensing dependencies.

The Unreal Engine Viewport Streaming Paradox

Another devastating error occurs when infrastructure engineers deploy consumer-grade open-source streaming software to transmit isolated user sessions over remote connections. Inside enterprise-level virtualization layouts, consumer applications encounter critical virtual monitor errors.

Because consumer tools are built entirely around physical display outputs and standard desktop driver architectures, they fail to map virtual layouts properly. This causes immediate display initialization exceptions and crashes the viewport editor environment instantly.

Elite architectures completely avoid consumer utilities, mandating the use of certified enterprise display protocols like HP Anyware (Teradici PCoIP) or Citrix HDX. These professional systems are engineered specifically to communicate with enterprise grid drivers, handling complex display allocations flawlessly. This infrastructure guarantees that remote digital artists experience absolute visual accuracy, exact peripheral input response, and perfect mouse precision directly within their virtual edit pipelines.

Defeating the “Noisy Neighbor” Shader Compilation Crisis

The most destructive obstacle within shared graphics infrastructure is compute noise management. Game rendering loops rely heavily on massive system memory speeds and multi-thread processor operations. When an individual software developer triggers a massive asset migration or initiates a 10,000-item shader compilation sequence, that specific action can instantly consume the entire host central processing cache.

Without rigorous orchestration isolation, this massive compute spike starves every adjacent slice on the physical hardware. Nearby designers experience immediate viewport decay, dropping from a fluid performance straight down to a lagging 5 frames per second interface.

To prevent this severe disruption, you must enforce strict NUMA node pinning and hard core-isolation protocols within the hypervisor layer, locking each development profile to dedicated, unshared processor silicon boundaries. Attempting this pinning routine on low-core budget processors causes massive CPU starvation because the server lacks the physical thread density required to separate concurrent multi-user workloads cleanly.

The Physical Distance Trap and Viewport Latency

Many infrastructure engineers fall into the technical trap of evaluating server virtualization setups purely based on network bandwidth capacity. Proclaimers brag about provisioning massive pipelines to transmit data allocations across global distances. In the engineering reality of real-time interactive streaming, this represents a critical misconception.

High-capacity network channels merely dictate data volume limits. Delivering responsive, low-latency viewports depends entirely on physical distance and network jitter control. If a software modeler situated in the United States attempts to interact with an active development workspace hosted inside an overseas datacenter, they will face a devastating 100ms round-trip latency anomaly. This physical delay generates immense input lag, rendering precise 3D positioning tasks completely unviable. Studio deployments must physically match hardware hosting hubs to the immediate regional location of their remote workforce footprints.

Studio Infrastructure Technical Matrix

Metric / Feature Legacy Desktop Sprawl Proprietary Cloud / VDI ServerMO Open SRE Architecture
Hardware Efficiency Low (Idle overnight) High (Shared compute) Maximum (Custom dedicated density)
Licensing Overhead None High (Broadcom/VDI tax) Zero (Proxmox VE / KubeVirt)
Viewport Performance Local raw speed Variable latency / Egress costs Low latency (Regionally matched hubs)
Compute Protection Inherent isolation Software boundaries Strict NUMA Node Core Pinning
Streaming Protocol Direct Display output Variable / Consumer tools HP Anyware / Teradici PCoIP

Bespoke Enterprise ServerMO Bare Metal Infrastructure

ServerMO completely eliminates rigid template limitations and regional latency barriers by offering a fully custom, scalable bare-metal provisioning pipeline. We understand that your multi-user graphics factory demands massive core density and localized positioning to guarantee smooth viewport performance.

Our expert distributed systems engineering team works hand-in-hand with your studio architecture staff to analyze your specific workforce distribution, compilation load, and concurrent user maps to build your hardware layout from the ground up inside your preferred target datacenter region.

Studio Infrastructure FAQ

Why can I not run 48 concurrent developers on a single 96GB Blackwell GPU?
Dividing 96GB across 48 users leaves precisely 2GB of video memory per session. Modern game engines require an absolute minimum of 12 to 16 Gigabytes merely to launch a blank project without triggering fatal out-of-memory exceptions. A single Blackwell card realistically supports a maximum of 6 to 8 elite developers.

Why should studios avoid proprietary hypervisors like VMware for graphics virtualization?
Proprietary virtualization stacks impose severe annual licensing inflation and corporate subscription taxes per user session. Deploying open-source platforms like Proxmox VE KVM or Red Hat OpenShift KubeVirt delivers identical raw performance and robust hardware access while completely eliminating expensive corporate licensing overhead.

Why does a high-bandwidth port fail to solve remote viewport input lag?
Bandwidth merely dictates data volume capacity while interactive viewport streaming relies entirely on network round-trip latency and physical distance. Connecting to an overseas data center introduces physical ping delays and jitter that cause severe input latency during 3D modeling. You must deploy servers in a region immediately adjacent to your remote design workforce.

Why is a budget low-core processor dangerous for multi-user game development servers?
Budget processors lacking high core density will suffer massive compute starvation when multiple developers execute parallel shader compilation pipelines simultaneously. Without adequate physical cores, you cannot implement strict NUMA node pinning, causing a single heavy task to freeze the active viewports of every adjacent developer on the server.

🔗 Connect with ServerMO Engineers to Build Your Bespoke Hardware Setup: ServerMO GPU Dedicated Servers Fleet

Leveling up from Class 10 ICSE to Polytechnic! Here is why I think even beginners need to look at code through a security lens. 👁️💻

Hey everyone! 👋

I’m Ch Hima Kartikeya Naidu. I just finished my Class 10 from an ICSE school, and I’m about to start my diploma journey. My ultimate dream is to build a career in Cyber Security, but on the side, I’m also a small-scale game developer who loves using storytelling and creativity to craft engaging narratives and virtual worlds.

Since I’m just entering polytechnic, my programming peak right now is mastering loops Python and C. I aced basic Java in my academics. While learning how loops repeat actions to make games work, I started wondering: How do these same basic programming concepts connect to cyber security?

Here is how I’m looking at security as a beginner dev:

  1. When Loops Turn Into Security Flaws (Infinite Loops)

In my classes, I learned how to use loops to repeat code until a condition is met. But what happens if a programmer makes a mistake and the loop never stops? It creates an infinite loop that freezes the software. In the security world, if an attacker finds a way to trigger an infinite loop on a server, they can crash the whole system. This is a basic form of a Denial of Service (DoS) vulnerability.

My Lesson: Writing secure code starts with making sure your loops always have a foolproof exit strategy.

  1. Game Exploits vs. Real-World Hacking

As a small-scale game dev, I know that if you don’t secure your variables, players can use memory-editing tools to change their in-game currency or health from 10 to 9999. In the cyber security world, this is very similar to a “Buffer Overflow” or memory tampering, where an attacker alters data in a computer’s memory to make it do things it shouldn’t.

My Lesson: Whether it’s a video game or a secure database, you can never trust what’s happening on the client’s side without validation.

  1. C Language and Memory Safety

Learning C has been eye-opening because it forces you to manage memory yourself. A lot of famous cyberattacks happen because of vulnerabilities in C-based software where memory isn’t handled safely.

My Lesson: Learning loops and memory management in C right now isn’t just academic—it’s actually the first step to understanding how system-level exploits work.

💡 Final Thoughts:
I might only know the basics right now, but I’m realizing that you don’t need to be a master hacker to start thinking about security. It starts with the very first loops and variables we learn in school. I can’t wait to level up both my security knowledge and my game dev skills during my diploma!

To the seniors in the community: What’s a basic coding habit you think every beginner should learn to write safer code from day one? Let’s hear it! 🚀

I corrected my AI email security analysis — 6 companies have real gaps

Yesterday I published an analysis claiming that 26 of 39 AI companies use SPF softfail, implying their email could be spoofed. A reader (@privacyfish) pointed out that this is misleading:

SPF ~all by itself does not always mean “the domain can be spoofed into inboxes” if the domain has DMARC enforcement and DKIM alignment working.

They’re right. SPF is only one layer. The actual spoofability of a domain depends on how SPF, DMARC, and DKIM work together — and DMARC only needs one of SPF or DKIM to align for the message to pass. So I re-ran the analysis with a combined scoring model.

How email authentication actually works

Layer What it does On its own
SPF Lists authorized sending IPs Softfail (~all) = “flag but deliver”
DMARC Tells receivers what to do on authentication failure p=reject = hard enforcement
DKIM Cryptographic signature proving the email is authentic Verifies message integrity

The critical point I missed: DMARC passes if either SPF or DKIM aligns with the From domain. A domain with SPF softfail + DMARC reject + DKIM = well-protected, because even if SPF softfails, aligned DKIM makes the DMARC check pass. And if both fail, DMARC reject tells the receiver to drop the message.

Checking SPF alone — which is what my original analysis did — misses the full picture.

Corrected results: 30 protected, 3 partial, 6 with gaps

Out of 39 AI/tech companies rescanned with all three layers:

Well-protected (30 companies)

These have DMARC enforcement (reject or quarantine) plus at least one aligned authentication mechanism:

Company SPF DMARC DKIM
Anthropic softfail reject google
OpenAI hardfail reject google
Apple softfail quarantine selector1
Microsoft hardfail reject selector2
Cloudflare hardfail reject k1
Stripe softfail reject google
DeepSeek hardfail quarantine default

(+ 23 others including Cohere, Mistral, Midjourney, Perplexity, Databricks, Snowflake, Cursor, Vercel, Replit)

Anthropic — the company I highlighted yesterday as vulnerable — is actually textbook correct. Softfail SPF + reject DMARC + DKIM alignment = spoofed emails get rejected.

Partially visible (3 companies)

Company SPF DMARC DKIM found? Note
Google softfail reject not on standard selectors Almost certainly uses custom DKIM selectors — they invented the protocol
Meta redirect reject not on standard selectors Uses Proofpoint; custom selectors likely
Notion softfail quarantine not on standard selectors DMARC enforcement active via SPF alignment

Important caveat: DKIM selectors are arbitrary strings chosen by the domain owner. My scanner checks 9 common selectors (google, selector1, selector2, default, k1, s1, s2, dkim, mail). Google and Meta almost certainly sign with DKIM using selectors I didn’t check. These companies have strong DMARC enforcement and are not practically at risk.

Authentication gaps (6 companies)

These have no DMARC enforcement — their DNS policies don’t instruct receivers to reject authentication failures:

Company SPF DMARC DKIM Gap
Nvidia softfail missing yes No DMARC policy at all despite having DKIM
xAI softfail p=none no Monitoring-only DMARC, no DKIM, Chinese email infra
Stability AI softfail p=none yes Has DKIM but DMARC won’t enforce on failure
Hugging Face softfail p=none yes Same — DKIM present but DMARC is monitoring-only
Inflection AI softfail missing yes No DMARC at all
Qdrant softfail p=none no No enforcement on any layer

p=none means the domain owner is collecting DMARC failure reports but not asking receivers to act on failures. It’s a standard first step when deploying DMARC — you monitor before enforcing — but some companies stay in monitoring mode indefinitely.

This doesn’t mean these companies’ email is actively being spoofed. It means their DNS configuration doesn’t instruct receiving mail servers to reject spoofed messages. Whether spoofing succeeds in practice depends on the receiving server’s own policies.

Nvidia is the most notable gap. A $3 trillion company with DKIM set up but zero DMARC policy — they started the process but didn’t finish it.

What changed from yesterday?

Metric SPF-only analysis Combined analysis
Companies with gaps 26 (67%) 6 (15%)
False alarms — 20 companies mislabeled as risky
Layers checked SPF only SPF + DMARC + DKIM

The original analysis was technically accurate — 26 companies do use SPF softfail — but practically misleading, because most are protected by DMARC enforcement.

Check any domain yourself

I updated the interactive checker to show a combined spoofability risk score that weighs all three layers. Enter any domain and get SPF policy + DMARC enforcement + DKIM presence + an overall assessment.

Data pulled live from public DNS records via DomainIntel. All claims independently verifiable with dig.

Correction prompted by @privacyfish’s comment on the original article. Data collected May 21, 2026.

I open sourced memduck, a self-hosted AI memory workspace

memduck product preview

memduck product preview

I built memduck because useful context keeps disappearing across links, copied text, screenshots, and chat messages.

Most of my actual working memory is not in one clean notes app. It is spread across browser tabs, saved links, snippets, screenshots, Telegram messages, and random text I copied while researching something. Later, when I want to ask a question about that material, I usually have to reconstruct the context manually.

memduck is my attempt at a small, self-hosted workspace for that problem.

GitHub: https://github.com/tageecc/memduck

What it does

memduck lets you save material from browser pages, pasted text, screenshots, and chat channels into a local memory workspace. Then you can ask questions against the saved material and trace answers back to the original sources.

The current version includes:

  • a Next.js workspace for asking and managing saved memory
  • local SQLite storage and local file assets
  • browser extension capture
  • channel configuration for browser, Telegram, DingTalk, Slack, Discord, Feishu, WhatsApp, and webhook-style inputs
  • model/provider configuration in the UI
  • background compilation for summaries, topics, embeddings, and retrieval data

Why self-hosted

I wanted this to be closer to a personal memory engine than another hosted knowledge app. The goal is to keep the runtime simple enough to inspect and run locally, while still making AI retrieval useful.

It is still early, but it is already useful for the workflow I care about: save context first, ask later, and keep the source trail visible.

Try it

npm install -g memduck@latest
memduck

Or from source:

git clone https://github.com/tageecc/memduck.git
cd memduck
pnpm install
pnpm memduck dev

If you care about local-first tools, personal knowledge workflows, or AI memory with source-backed answers, I would like feedback.

Visual Guide to TCP at the Transport Layer


I built a detailed visual diagrams for the Transmission Control Protocol (TCP) — one of the core protocols powering the internet, that operates at the Transport Layer (Layer 4) of the OSI model.

I broke down:
🔹 TCP Segment Structure: –
Source & destination ports
Sequence number
Acknowledgment number
Flags (SYN, ACK, FIN, RST, PSH, URG)
Window size
Checksum
Options & payload
Here the full animated diagram svg link of TCP structure: – https://github.com/knkrn5/Programming-Concepts/blob/main/computer-networking/protocols/transmission-control-protocol/TCP-segment/tcps.svg


🔹 TCP 3-Way Handshake: –
SYN
SYN-ACK
ACK
Sequence & acknowledgment numbers
Window size negotiation
MSS negotiation
How a connection becomes ESTABLISHED
Here the full animated diagram svg link of TCP handshake: – https://github.com/knkrn5/Programming-Concepts/blob/main/computer-networking/protocols/transmission-control-protocol/tcp-handshake/tcph.svg

While studying networking, I realized many resources explain TCP theoretically but not visually.
So I created these diagrams to make the packet flow and header fields easier to understand step-by-step.

One thing I found especially interesting:
TCP reliability is achieved through sequence numbers, acknowledgments, retransmissions, and flow control — all working together behind the scenes every time we browse a website or send data online.

Understanding protocols at this level really changes how you see networking and distributed systems.

Infrastructure as Vibe: What Comes After Infrastructure as Code

A friend of mine sent me a screenshot last week. Eight tabs. Vercel, Neon, Cloudflare, GitHub, Stripe, Resend, a Notion doc with env vars, and a terminal running ngrok. He was three hours into “just deploying a side project” and had not written a line of product code yet. The message under the screenshot said: “tell me again why this is the good timeline.”

I laughed because I have lived this exact afternoon at least fifty times. You know the stack you want. You know which buttons to press. The CLIs are great individually. None of them talk to each other. So you become the wetware integration layer, copying connection strings into env files, pasting CNAME records into DNS panels, remembering which secret needs to be rotated where.

That experience is the friction that gave the next paradigm its name. Infrastructure as Vibe. The phrase started as a joke on Twitter, but enough people stopped laughing for it to become a real category. Neon’s official account endorsed it on stage. Cloudflare’s team has been hinting at it in every product update for six months. The pattern is showing up everywhere even when people do not use the term.

This article is about what “infrastructure as vibe” actually means as a paradigm, why it became inevitable, what it gets right, what it gets dangerously wrong, and where developer tooling is heading because of it.

From Infrastructure as Code to Infrastructure as Vibe

To understand why this matters, you have to remember what each previous layer was a reaction to.

In the early 2010s, deploying anything to production meant clicking through AWS consoles, SSHing into boxes, and praying you remembered to set the security group correctly. People called this ClickOps. It was a disaster for reproducibility. You could not version it. You could not review it. The person who set it up was the only one who knew what it looked like, and the moment they left the company, the infrastructure became a haunted house.

Infrastructure as Code was the response. Terraform, CloudFormation, later Pulumi and CDK. Declare your infrastructure in a file. Commit the file to git. Run a command. Get the same environment every time. Everyone who has ever maintained a real system understands why this was a good idea.

But IaC carried a tax that nobody really wanted to pay. You now had to learn HCL, or YAML schemas, or a TypeScript-flavored DSL that pretended to be regular code but very much was not. You had to keep state files. You had to understand provider versions. You had to debug why your apply hung for nineteen minutes because someone deleted a resource in the console. You had to write 400 lines of config to deploy something that, in your head, was “a Node app and a Postgres database.”

GitOps, Helm charts, and Kubernetes operators were attempts to make this nicer. They mostly added more files to learn. Then PaaS providers like Heroku, Vercel, Render, Railway, and Fly came back into fashion because they let you skip most of that. The pattern was “git push and we figure it out.” That worked great until you wanted to do anything slightly outside the happy path. As soon as you needed a database in a different region, or a queue that talked to a worker, or a domain that pointed at two services, you were back in five dashboards.

Infrastructure as Vibe is the layer that sits on top of all of this. The interface is plain language. The implementation is “we figure out the right APIs to call.” You describe what you want in the way you would describe it to a colleague who happens to know every platform’s quirks. The system reads your intent, scans your code, makes opinionated choices, and shows you what it provisioned.

If IaC was about removing humans from the imperative step, Infrastructure as Vibe is about removing humans from the declarative step too. You stop writing configuration entirely. You write intent.

What “Infrastructure as Vibe” Actually Means

The phrase is catchy enough that people are already using it to mean different things, so let me be specific about what it actually describes as a paradigm.

There are three properties that have to be true for a tool to fit this category.

The interface is natural language, not configuration. You do not fill out a form. You do not edit a YAML file. You type or say what you want. “Deploy this repo. Add a Postgres. Point it at myapp.com.” The system parses that, infers the gaps, and confirms before doing anything destructive.

Inference replaces declaration. Traditional IaC requires you to specify every detail because the tool refuses to assume. Infrastructure as Vibe inverts that. The tool reads your code, your dependencies, your existing project, and makes structural assumptions based on what it sees. If your package.json includes prisma and pg, you probably want Postgres. If you have @supabase/supabase-js, you probably want Supabase. If you have mongoose, you want Mongo. You can override anything, but the default is “guess correctly most of the time.”

The platform absorbs the integration work. This is the part that distinguishes Vibe from “just a wrapper over Terraform.” A real Infrastructure as Vibe tool does not just generate config and hand it back. It calls the APIs, watches the rollout, handles the failure modes, retries the flaky ones, and tells you when it is done. You do not get a 200-line plan to apply yourself. You get a result.

You can argue about whether all three need to be present. I would say yes, because if you remove any of them, you collapse back into a previous paradigm. Strip the natural language and you have a smarter PaaS. Strip the inference and you have ChatOps that just calls a CLI. Strip the integration work and you have a clever assistant that drafts Terraform.

The combination is what makes it new. And the combination is what makes some developers nervous.

The Friction That Made This Inevitable

You can see the demand for this paradigm if you look at what developers actually complain about online. Not what they say in conference talks. What they post at 11pm on a Tuesday after their fifth deploy attempt.

The complaints cluster into a few categories that should be familiar to anyone who has shipped a side project in the last three years.

Tab fatigue. Every PaaS has a console. Every database has a console. Every domain registrar has a console. Every observability tool has a console. You are not really using each one. You are using all of them as a single distributed system that someone forgot to integrate.

Bill shock. This is the most consistent complaint across Vercel, Render, Neon, Supabase, and Fly. Usage meters that run while you sleep. No hard caps. You read a forum post in the morning explaining that someone got a $4,000 bill because their cron job hit an infinite loop. You spend the next hour wiring spend alerts and budget guards. That hour is not building product.

Secret sprawl. A modern app has, on average, somewhere between twelve and twenty environment variables across staging and production. You set them in three different dashboards. You forget which is which. You leak one into a screenshot during a demo. You promise yourself you will rotate them later. You do not.

DNS purgatory. You buy a domain. You point it at a service. The TTL is 24 hours and the CNAME is fighting an A record. You verify ownership through a TXT record that takes 45 minutes to propagate. You check dig in three terminals. You add a www subdomain and the redirect breaks. You forget to renew the cert. The cert renews automatically and you forget you ever worried about it.

None of these are theoretical. They are the unpaid labor of being a modern developer. Every one of them is something a sufficiently smart tool could absorb. The reason none of them got fully absorbed sooner is that no single platform owned the whole stack. Vercel cannot fix your Neon bill. Neon cannot fix your DNS. Your DNS provider cannot fix your secret rotation. Somebody had to play orchestrator. Until recently, that somebody had to be you.

The shift toward natural language as a universal interface, combined with the agentic tooling I wrote about in agentic coding, changed the math. A coordination layer that calls every platform’s API on your behalf no longer needs to be a Heroku-scale company. It can be a relatively small orchestration service with good prompts, good defaults, and a careful integration layer.

That is why this paradigm is showing up now and not five years ago.

Where You Can Already See It

You can spot Infrastructure as Vibe in the wild even when nobody is calling it that.

When Vercel added “deploy from a screenshot” and “deploy from a sentence” via v0, that was the paradigm leaking into a frontend product. You did not configure anything. You described something. The platform figured out the rest.

Cloudflare has been pushing in the same direction with their AI gateway and their increasingly chat-driven control plane. You can describe a worker, get a worker, attach a domain, all without ever opening a config file. They are not marketing it as “infrastructure as vibe,” but the shape of the experience is unmistakable.

Render’s blueprints have been quietly turning into something similar. Drop a repo in, accept the inferred services, click deploy. The friction between “I have an idea” and “it is live on the internet” gets compressed every release.

The most aggressive version of this is what is happening through coding agents themselves. Claude Code, Cursor agents, and the various MCP-driven orchestrators can now provision a database, push a deploy, configure a domain, and rotate a secret from a single prompt, given the right tools. The “infrastructure” is the LLM’s tool calls. The “vibe” is the prompt. It looks weird the first time you see it. The second time it looks inevitable.

There are also a wave of newer tools whose entire pitch is the paradigm. Some are general purpose orchestrators. Some are stack-specific. Some are aimed at non-technical founders who never wanted to learn the difference between an A record and a CNAME. The tools differ. The pattern does not.

If you squint, you can also see this pattern in adjacent categories. Stripe Apps and shadcn/ui blocks both reduce the cognitive load of “I need this thing” to a one-line invocation. They are not infrastructure, but they share the same posture: assume good defaults, do the integration work for me, let me describe outcomes instead of steps.

Why Developers Resist It

This paradigm is not universally welcomed, and the resistance is not stupid. Most of it comes from real scars.

Loss of control. A developer who has been burned by a magical platform will be suspicious of any tool that says “trust me, I will figure it out.” They want to see the plan. They want to read the Terraform. They want to know what the security group looks like. The Vibe layer hides that by default, and that is the right design choice for most users and the wrong choice for some.

Black box anxiety. When something breaks at 3am, you need to know what got provisioned, where, with what permissions. If the provisioning happened through a chat interface and the audit log is “Claude decided,” that is not a debugging story. That is an incident report you have to write to your CTO.

Comprehension debt. I wrote about this in the vibe coding revolution in the context of code. It applies just as forcefully to infrastructure. The developer who never learned what a security group is, because a friendly tool always set it up correctly, is going to have a bad time the first time the tool gets it wrong. And the tool will eventually get it wrong, because every tool does.

Vendor lock-in. A coordination layer that owns your deploy, your database, your DNS, and your secrets is also a single point of failure for your entire stack. If the company behind it gets acquired, raises prices, or pivots, you may not have an exit strategy. IaC at least gave you portable files. Vibe gives you outcomes that are difficult to reproduce on a different platform without redoing the work.

Existing skill obsolescence. A developer who spent five years getting good at Terraform is not enthusiastic about a paradigm that says the Terraform expertise is now a niche specialty. This is a human reaction, not a technical one, but it shapes adoption.

These are all legitimate concerns. The right response to them is not “trust the magic.” It is to design Vibe tooling that surfaces the underlying reality on demand. Show me what got created. Show me the cost projection. Show me where to override. Give me an escape hatch back to raw config. The good versions of this paradigm will be the ones that respect the people who want to look under the hood.

When Infrastructure as Vibe Works and When It Fails

Like every paradigm before it, this one has a fitness landscape. It is not universally better. It is meaningfully better in some places and meaningfully worse in others.

It works great for:

  • Side projects and prototypes. The whole point is getting from idea to live URL in minutes. The cost of being wrong is low. The cost of being slow is the project dying before launch.
  • Solo developers and small teams. The integration work is a tax that hurts small teams the hardest. Removing it gives them back a measurable percentage of their week.
  • Greenfield production apps with standard stacks. If you are building a Next.js app with Postgres and Stripe and Resend, the default choices a Vibe tool would make are probably the same choices you would have made.
  • Founders and designers without a dedicated devops person. The alternative is hiring someone or hand-waving DNS for a year. This is a real, expensive choice that this paradigm collapses.

It is risky for:

  • Regulated environments. Healthcare, fintech, public sector. You need explicit, auditable, declared infrastructure for compliance reasons. Vibe-style provisioning is not yet the right shape for SOC 2 audits, even though it can in principle generate the artifacts.
  • Large existing systems. A coordination layer that is good at clean deploys is not necessarily good at integrating with a fifteen-year-old VPC, three legacy databases, and a custom IAM model. The brownfield problem is brutal.
  • Mission-critical production with hard SLOs. When 99.95% matters, you cannot afford “the platform chose for me.” You need to make every choice deliberately and review it.
  • Anyone who hates leaky abstractions more than they hate friction. Some developers are wired to want to see the bytes. They will be miserable on top of a Vibe layer no matter how well it works.

The honest version of this paradigm acknowledges those tradeoffs instead of pretending the line is everywhere. You can use Infrastructure as Vibe to ship a prototype in an afternoon and still believe that your bank should run on hand-written Terraform. Both of those statements can be true at the same time.

The Vibe Stack Underneath

Let me get a little more concrete about how this actually works under the hood, because “the AI does it” is not a real answer.

Most viable Infrastructure as Vibe systems sit on top of a layer cake that looks something like this.

Deterministic detection comes first. You do not ask the LLM what database to provision. You scan the package.json, the lockfile, the go.mod, the Cargo.toml. You read framework signatures from imports. You check for known config files. This is fast, free, and reliable. The LLM only gets called when the deterministic layer is genuinely ambiguous.

Intent parsing is where the LLM earns its keep. Translating “deploy this and add a database, point it at app.example.com” into structured calls is exactly the kind of task small fast models like Claude Haiku are good at. The output is not freeform. It is a constrained schema that the orchestrator can execute. No code generation. No hallucinated APIs. Just structured decisions.

Orchestration is plain old engineering. A long-running service, a job queue, a Redis somewhere, and careful integration code that knows how every target platform actually behaves. This is the part that takes the longest to get right and is the hardest to fake with a demo. Anyone can ship “I called the API.” Far fewer people ship “I called the API, handled the rate limit, retried the flaky one, rolled back the partial state when the third call failed, and gave you a useful error message.”

Cost transparency lives in the middle. Before anything destructive happens, the system tells you what it is about to do and what it estimates the monthly cost will be. This is the answer to bill shock and it is what separates a serious Vibe tool from a fancy CLI wrapper.

Audit logging is the floor. Every provisioned resource, every config decision, every secret rotation gets logged with timestamps, model versions, and the original prompt. When something breaks, you need to be able to reconstruct exactly what happened. The version of this paradigm that does not log carefully will not survive contact with real users.

The reason this stack matters is that it shows the paradigm is not “vibes all the way down.” Most of it is conventional, careful software engineering. The vibe is at the surface. The substrate is the same kind of integration work that has always been required to make platforms talk to each other. The trick is that the substrate is finally getting built, because the surface is finally compelling enough to justify the investment.

What Has to Be True for This to Actually Work

Predictions are cheap. Let me make some falsifiable ones.

For Infrastructure as Vibe to graduate from “interesting demo” to “default way most apps get deployed in 2028,” a few conditions have to hold.

Reversibility has to be cheap. If I can ask the system to provision something and then ask it to undo cleanly, I will use it. If undoing requires me to log into five dashboards and clean up orphans, I will not trust it again. The good tools will make destroy as fluent as create.

Cost has to be visible before action. Every command that costs money should show its cost first. Every recurring resource should show its monthly projection. This is non-negotiable. Bill shock is the single biggest reason people abandon PaaS, and any Vibe layer that does not solve it is one bad incident away from a viral horror story.

Audit has to be ambient. Not a feature you turn on. Always on by default. Every action provenanced. Every secret rotation recorded. The audit log is what unlocks regulated use cases later.

The escape hatch has to be real. “Export to Terraform” or “show me the underlying calls” cannot be a roadmap item. It is the price of trust. If a developer feels trapped, they will not adopt. If they can leave, they probably will not.

Defaults have to be opinionated, not naive. A tool that asks me twelve questions is worse than the dashboard it replaces. A tool that picks reasonable answers and lets me override is the entire point. The opinions need to be good ones, which means real product decisions, not arbitrary ones.

If those conditions hold, the paradigm wins for most new applications. If they do not, this becomes another era of demos that did not generalize. Both outcomes are plausible. I am betting on the first one because the underlying technology curve, particularly the cost and reliability of structured LLM output, is moving in the right direction every quarter.

Where This Goes Next

I keep thinking about how this connects to the broader shift toward spec-driven development. In code, the spec is becoming the source of truth and the code is generated from it. In infrastructure, the intent is becoming the source of truth and the config is generated from it. Same pattern, different layer. The end state is that human-written declarative config might become as rare as hand-written assembly is today. It will still exist for the cases that need it. It will not be the default.

The teams that move fastest will be the ones who treat infra as a means, not as a craft. Not because the craft does not matter, but because most of the time, the right amount of craft to apply to “ship this prototype tonight” is none. The same developer who insists on hand-tuned config for a financial service will happily let the Vibe layer handle their weekend project. That bifurcation is the natural shape of the next few years.

The risk worth watching is consolidation. A handful of companies will become the orchestration layer between all the platforms. They will know what you deploy, what you spend, what you store, and where your traffic comes from. That is enormous power. The paradigm only works socially if the tools at the surface compete hard enough that no single one becomes the lock-in story for the entire web.

I also expect this to push the underlying platforms toward better, more predictable APIs. If your value as a database, hosting provider, or DNS service is increasingly mediated through an orchestration layer, your API ergonomics matter more than your dashboard ergonomics. That should be good for everyone. The platforms with the cleanest APIs are about to win an asymmetric amount of new business.

The interesting question for the next few years is which of the giant providers, the existing PaaS players, or the newer orchestration startups end up owning the surface. I do not know the answer. I do know the surface is moving from forms to sentences, and from documents to conversations, and that is not going back.

My Take

I have been deploying things for most of a decade. I have written more Terraform than I want to admit. I have set up Vercel projects in my sleep. I know the muscle memory. I am still tired of doing it.

The honest reason Infrastructure as Vibe is going to win for most use cases is not that the technology is magical. It is that the alternative is bad. Modern application infrastructure asks every developer to be a part-time platform engineer. That was tolerable when there were three platforms. It is not tolerable when there are thirty. The integration work has gotten worse every year, and developers have absorbed it because there was no other option. Now there is one.

The version of this paradigm that fails is the one that hides too much. Black-box magic that you cannot inspect, cannot reverse, cannot afford to break. That version will get one good demo cycle and then a thread of horror stories that kill it. The version that wins is the one that defaults to friction-free and treats the underlying truth as something you can always pull up. Good defaults, visible cost, clean audit, easy exit.

If you are building developer tools, the lesson is to take the integration work seriously even when the surface looks easy. The fluency of the chat interface is the marketing. The brittleness of the third API call you make under the hood is the product. The companies that win this category will be the ones that obsess over the unsexy substrate.

If you are a developer who has resisted this paradigm, I would not blame you. Most prior “we make infrastructure easy” pitches were wishful thinking. This one feels different because the AI layer makes the inference step finally cheap, and the existing platform CLIs are finally good enough to chain reliably. The two missing pieces showed up at the same time.

Infrastructure as Code did not kill the console. PaaS did not kill IaC. Infrastructure as Vibe will not kill PaaS. Every layer continues to exist. The default just moves up. The thing you reach for first when you start a new project keeps getting closer to “here is what I want to build.” That progression is the whole story of developer tooling. Vibe is the next stop on a road we have been walking for thirty years.

I will keep my Terraform skills sharp. I will also keep typing sentences and watching apps appear. Both of those can be professional. Pretending only one of them is, at this point, is just nostalgia in a hoodie.

I built my own uptime monitor because UptimeRobot felt cluttered – here’s what I learned

I built my own uptime monitor because UptimeRobot felt cluttered — here’s what I learned

The problem

I’ve been using UptimeRobot for a while. It works, but every time I opened it I felt like I was looking at a dashboard designed for enterprise teams. I just wanted to know: is my site up? If not, tell me. That’s it.

So I built my own.

What I built

PingBoard — uptime monitoring with public status pages. Monitors URLs on a schedule, sends alerts when things go down, and generates a clean shareable status page for your users.

5 monitor types: HTTP, keyword, DNS, API, and heartbeat.

The stack

  • Next.js 14 App Router + TypeScript
  • Convex — backend, DB, cron jobs, realtime subscriptions
  • Clerk — auth
  • Resend — email alerts
  • Lemon Squeezy — payments (Stripe isn’t available in India)
  • Framer Motion — animations

The interesting parts

Realtime status pages without WebSockets

Convex’s reactive queries mean the public status page updates instantly when a monitor goes down — no polling, no manual WebSocket management. Just a useQuery hook and it works.

The ping loop

A Convex cron fires every 30 seconds, finds monitors that are due for a check, and schedules individual check actions per monitor. Each check runs independently — one slow site doesn’t block others.

Heartbeat monitoring

Instead of PingBoard pinging your service, your service pings PingBoard. Useful for cron jobs and background workers. If PingBoard doesn’t hear from your job within the expected interval × 1.5, it opens an incident.

Payments from India

Stripe isn’t available in India so I went with Lemon Squeezy. Acts as merchant of record — handles VAT, GST, tax compliance automatically. Checkout was live in a day.

What I’d do differently

  • Started with Convex from day one — initially considered Supabase but switched early and never looked back
  • Underestimated how much time auth takes — Clerk saved probably 2 weekends
  • Should have verified the Resend domain earlier (still in sandbox mode — alerts only reach verified addresses)

Where it is now

Live at ping-board-monitor.vercel.app. Free tier, no credit card. Built for myself, a friend convinced me to open it up.

Would love feedback — especially from devs who’ve felt the same frustration with existing tools.

GraphQL là gì — Tại sao nên dùng cho Social App?

GraphQL là gì — Tại sao nên dùng cho Social App?

1. GraphQL là gì?

GraphQL là ngôn ngữ truy vấn cho API, do Facebook phát triển năm 2015. Thay vì server quyết định bạn nhận được gì, client tự chỉ định chính xác dữ liệu mình cần.

So sánh nhanh với REST

REST GraphQL
Endpoint Nhiều (/users, /posts…) Chỉ 1 (/graphql)
Dữ liệu trả về Fixed, server quyết định Linh hoạt, client quyết định
Over-fetching Thường xuyên Không bao giờ
Under-fetching Phải gọi nhiều request Lấy 1 lần được hết

3 khái niệm cốt lõi

  • Query — đọc dữ liệu (như GET)
  • Mutation — thay đổi dữ liệu (như POST/PUT/DELETE)
  • Subscription — lắng nghe realtime (như WebSocket)

2. Tại sao GraphQL phù hợp với Social App?

2.1 Một request — render cả trang

Feed social cần render cùng lúc: avatar, tên user, ảnh post, số like, top comment…

REST: 4–5 request tuần tự hoặc song song

GET /feed
GET /users/:id
GET /posts/:id/likes
GET /posts/:id/comments

GraphQL: 1 request duy nhất, server tự resolve

query Feed {
  feed {
    author { avatar name isFollowing }
    content images
    likes { count isLikedByMe }
    topComments { text author { name } }
  }
}

→ Giảm latency, giảm round-trip, render nhanh hơn rõ rệt.

2.2 Lấy đúng field cần — không thừa, không thiếu

Màn hình khác nhau → nhu cầu data khác nhau:

Màn hình Cần gì
Feed (thumbnail) name, avatar, title, likeCount
Post detail thêm fullContent, comments, shares
Profile card chỉ name, avatar, followerCount

REST trả về cùng 1 response nặng cho tất cả. GraphQL cho phép mỗi screen query đúng field nó cần — đặc biệt quan trọng với mobile, tiết kiệm bandwidth đáng kể.

2.3 Frontend không cần “gom” data từ nhiều API

REST — FE phải tự join và normalize:

const user = await getUser(id)
const posts = await getPosts(id)
const followers = await getFollowers(id)

// Rồi tự map, merge...
const profileData = mergeAndNormalize(user, posts, followers)

GraphQL — server chịu trách nhiệm resolve mọi relationship, FE nhận về 1 object sẵn sàng dùng. Logic mapping nằm ở tầng resolver thay vì rải rác ở từng màn hình.

2.4 Caching & Batching — xử lý data lặp lại thông minh

Social feed hay có pattern: cùng 1 user xuất hiện ở nhiều post.

DataLoader pattern tự động batch + deduplicate:

Post 1 → author_id: 42  ┐
Post 2 → author_id: 17  ├─ DataLoader → 1 DB query duy nhất
Post 3 → author_id: 42  ┘   SELECT * FROM users WHERE id IN (42, 17)

Client-side (Apollo/urql) cũng normalize cache theo object ID — user cập nhật avatar ở 1 chỗ, toàn bộ feed tự cập nhật, không cần refetch.

2.5 Self-documenting — FE tự khám phá API

GraphQL có Introspection tích hợp sẵn: schema chính là documentation. Công cụ như GraphiQL / Apollo Sandbox cho phép:

  • Autocomplete field khi gõ query
  • Xem type, mô tả của từng field ngay trong IDE
  • Không cần Postman collection hay Swagger riêng

→ FE và BE làm việc từ cùng 1 source of truth — schema file. Thêm field mới, FE thấy ngay.

3. Pain Point thực tế: /api/auth/me

Đây là ví dụ điển hình về vấn đề REST gặp phải trong production.

Hiện trạng — trả về “tất cả hoặc không có gì”

// GET /api/auth/me
{
  "id": 123456,
  "name": "Nguyễn Văn A",
  "avatar": "https://...",
  "coin": 45200,
  "rank": "GOLD",           // ❌ aggregate loyalty_histories
  "rankProgress": 78.5,     // ❌ tính toán nặng
  "totalEarned": 1250000,   // ❌ SUM toàn bộ lịch sử
  "totalSpent": 890000,     // ❌ SUM toàn bộ lịch sử
  "referralCount": 12,      // ❌ COUNT từ bảng referrals
  "taskCompletedCount": 47, // ❌ COUNT từ bảng task_points
  "badges": [...]           // ❌ JOIN thêm bảng badges
}

Mỗi lần app load → gọi /auth/me → server tính toán tất cả, dù màn hình chỉ cần hiện tên + avatar.

Phân tích chi phí thực tế

Field Chi phí server Tần suất FE dùng
name, avatar, coin Rất thấp Mọi màn hình
rank, rankProgress Nặng — aggregate loyalty_histories Chỉ màn hình Profile/Rank
totalEarned, totalSpent Nặng — SUM toàn lịch sử Chỉ màn hình Thống kê
referralCount Trung bình Chỉ màn hình Referral
taskCompletedCount Trung bình Chỉ màn hình Task
badges Nặng — multi JOIN Chỉ màn hình Profile

→ 90% request /auth/me chỉ cần 3–4 field đầu, nhưng vẫn phải trả tiền tính toán toàn bộ.

Với GraphQL — lazy computation theo từng màn hình

App header (render mọi lúc):

query AppHeader {
  me {
    name
    avatar
    coin      # query cực nhẹ, chỉ SELECT 3 fields
  }
}

Màn hình Profile/Rank (user chủ động vào):

query ProfileScreen {
  me {
    name avatar coin
    rank          # chỉ tính khi user thực sự mở màn hình này
    rankProgress
    badges
  }
}

Màn hình Thống kê (vào ít nhất):

query StatsScreen {
  me {
    totalEarned       # heavy computation chỉ chạy khi cần
    totalSpent
    referralCount
    taskCompletedCount
  }
}

Kết quả

REST hiện tại GraphQL
App header load ~150ms (tính toán full) ~8ms (chỉ SELECT 3 fields)
Profile/Rank ~150ms (dù không cần) ~120ms (lazy, chỉ khi vào)
Server load (600K users) Tính rank cho tất cả Chỉ tính khi được query

Heavy field như rank trở thành lazy resolver — không tốn tài nguyên tính toán cho 600K user mỗi khi họ mở app.

How I shipped my PWA to Google Play as a TWA (and what actually went wrong)

I built Money Me as a PWA. It works offline, it’s installable, it feels like a native app. At some point I decided to put it on Google Play because people kept asking “is it in the store?”

The TWA route seemed obvious. Wrap the existing PWA in an Android shell, ship it. I figured a day of work, maybe two.

It took me a lot longer than that.

So what is a TWA

A Trusted Web Activity is basically an Android app that opens your website in Chrome, but with the browser UI stripped away. No address bar, no back button. Fullscreen. If you didn’t know better you’d think it was a regular Android app.

The “trusted” bit: you prove you own the domain by putting a specific JSON file on your server. Android checks it against your app’s signing key. If it matches, Chrome hides the browser chrome (pun maybe intended). If it doesn’t match, you get an ugly blue bar at the top and your app looks like a glorified bookmark.

Important thing I didn’t understand at first: a TWA is NOT a WebView. It’s actual Chrome running your site. Service workers work, push notifications work, everything your PWA already does just… works. This is the main reason to use a TWA over something like Capacitor or a WebView wrapper.

Bubblewrap

Google has a tool called Bubblewrap that generates an Android project from your web manifest. Point it at your manifest URL, it spits out a project, you build an APK.

My advice: don’t treat it as a black box. You will need to open the generated project and mess with build.gradle and the Android manifest at some point. If you’ve never seen an Android project before, spend 20 minutes understanding the structure first. You’ll thank yourself later when something breaks and the error message means nothing to you.

The blue bar (aka my nemesis for two days)

This is where I lost the most time. The blue navigation bar shows up when Chrome can’t verify you own the domain. Your app still works fine underneath, it just looks terrible.

The fix is a file at /.well-known/assetlinks.json:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.yourapp.twa",
    "sha256_cert_fingerprints": ["YOUR:SHA256:FINGERPRINT:HERE"]
  }
}]

Simple enough. Except I got the fingerprint wrong three times before figuring out what was happening.

The problem: you have multiple signing keys and they all have different fingerprints. There’s your local debug key, your upload key, and then Google Play’s own app signing key. Play App Signing is mandatory for new apps now, which means Google re-signs your bundle after you upload it. So the fingerprint that matters for asset links is Google’s key, not yours.

Go to Play Console → Setup → App signing → App signing key certificate and grab the SHA-256 from there. I wasted hours using my upload key fingerprint instead. The blue bar kept showing up and I kept double-checking the JSON format, the content type, the file path. The file was fine. The fingerprint was just wrong.

Other things that bit me:

Chrome caches the verification result. You fix the asset links file, reinstall the app, and… blue bar is still there. You need to clear Chrome’s data on the test device. Not just the cache. The data. I was clearing the app cache only and wondering why nothing changed.

Content-Type has to be application/json. My CDN was serving it as text/plain. Took me a while to catch that one.

Use Google’s verification tool. I should have used this from the start instead of guessing. It tells you exactly what’s wrong.

The signing key situation

If you’re a web developer, Android signing keys are confusing. There are two keys involved:

  1. Your upload key — you use this to sign the bundle before uploading to Play Console
  2. Google’s app signing key — Google uses this to sign the APK that actually gets distributed to users

For your asset links JSON, you need #2. Not #1. I keep repeating this because it took me an embarrassingly long time to figure out, and every tutorial I found either glossed over it or assumed you already knew.

Generate your upload key:

keytool -genkey -v -keystore upload-keystore.jks 
  -keyalg RSA -keysize 2048 -validity 10000 
  -alias upload

Then do your first upload to Play Console, and THEN go grab the app signing key fingerprint. You can’t get it before the first upload because Google generates it at that point.

Closed testing: the 12-tester gate

Once the app was building and the blue bar was gone, I thought I was done. Nope.

Google requires new apps to have 12 testers opted into a closed beta for 14 continuous days before you can go to production. You need real people with real Google accounts who join your testing program, install the app, and stay opted in for the full two weeks.

If you’ve got an existing user base, this is nothing. If you’re a solo dev shipping your first app, it’s a real bottleneck. I wrote a whole post about this already.

What I’d do differently next time

Get asset links working BEFORE you build the TWA. Host the JSON file, verify it with Google’s tool, confirm it’s correct. Then build the app. Debugging both at the same time is miserable.

Start looking for testers before your build is ready. The 14-day clock is the actual bottleneck, not the technical work.

Test on a Samsung phone early. My app looked perfect on a Pixel. Then I tried it on an older Galaxy and some things were off.

Is it worth it though?

Yeah. For a PWA that’s already working well, a TWA is the right call. One codebase, Play Store presence, native-feeling experience. The setup takes a weekend if you know the pitfalls. Compared to maintaining a separate React Native or Kotlin app? Not even a question.

The downside is you’re dependent on Chrome being installed, but that’s basically every Android phone. And you need to keep your asset links in sync when keys change. That’s about it.

I’m going through the closed testing process now with Money Me. If you’ve got an Android phone and don’t mind helping an indie dev clear the 12-tester gate, I’d massively appreciate it. Beta testers get 6 months of Premium free.

👉 Join the beta on Google Play

30 seconds to opt in. If you’ve got TWA questions, drop them in the comments — I’ve made most of the mistakes already.