AI 资讯
How to Scale Realtime Duplicate Event Delivery: Node.js Chat Reconnects
Short answer: make the event identity durable, deduplicate at the consumer boundary, and resume from a server-issued cursor; a client-side set alone cannot make a marketplace chat room survive reconnects or an incident-response burst. The constraint is trust. A browser reconnects after a laptop sleeps, a mobile radio changes networks, or a tab is restored from the back-forward cache. It may replay its last request, lose an acknowledgement, or present an event twice. In an incident response dashboard, the same mechanics become dangerous at scale: an alert that appears twice can page two people, while a missing alert can hide the incident. I design the storage boundary first, because a pretty WebSocket demo does not answer either question. Start with an event identity that can outlive a connection Every published event needs an immutable identity scoped to the stream, not to a socket. For a marketplace chat room, I use (room_id, sequence) as the primary key and keep a globally unique event_id for tracing. The sequence is allocated by the room writer, so two reconnecting clients can compare progress without trusting wall-clock timestamps. The payload is deliberately boring. It includes the room, sequence, event ID, type, and data. A client can verify that an event belongs to the room it requested; it cannot mint a higher sequence or widen its token scope. That last rule matters more than transport choice. from dataclasses import dataclass from typing import Any @dataclass ( frozen = True ) class ChatEvent : room_id : str sequence : int event_id : str event_type : str data : dict [ str , Any ] def identity ( event : ChatEvent ) -> tuple [ str , int ]: """ The room sequence is the replay-safe identity. """ return event . room_id , event . sequence Do not use a payload hash as the only key. Two legitimate messages can have identical text, and a producer retry can produce different JSON ordering. Persist the identity and the payload together, with a uniqueness constraint,
AI 资讯
Scaling Realtime Event Delivery for 10,000 Reconnecting Delivery Tracking Maps
For realtime release compatibility in a delivery tracking map, scale event delivery with a durable, ordered log per delivery and treat every browser connection as a disposable projection of that log. Presence can guide fan-out and capacity planning, but it must never decide whether a location update exists. Short answer: release compatibility comes from versioned envelopes, resume cursors, and an explicit resync path; scaling comes from partitioning by delivery ID and coalescing map updates at the edge, not from trusting a long-lived connection to carry every event exactly once. This decision targets an e-commerce tracking experience in which a shopper may open a map, lose connectivity in a tunnel, return on another network, and also join a delivery-specific support chat room. The deciding constraint is presence accuracy: an online indicator is useful only when its expiry rules are understood, while the delivery state must remain correct even when that indicator is late. A green dot isn't a commit log. How should realtime release compatibility scale event delivery in a delivery tracking map? Separate the system into three contracts: durable delivery state, transient room presence, and the connection used to move updates. The first contract owns truth. The second answers a narrower question: which sessions have renewed a lease recently enough to be considered reachable? The third may disappear at any point and should be replaceable without changing either of the other two. For each delivery, append an event with a monotonically increasing sequence within that delivery's partition. The client persists the last applied sequence and includes it when reconnecting. If retained events cover the gap, the server replays them in order; if they don't, the server returns a fresh snapshot plus its sequence. This is at-least-once delivery with idempotent application, which means duplicates are ordinary and gaps are detectable. It does not promise global order across unrelated del
AI 资讯
How to start building your own rtos
Why Build a Custom RTOS in 2026? Why build a custom RTOS when there are already tons of battle-tested ones like FreeRTOS or Zephyr available? It’s a fair question, but there's much more to it than just reinventing the wheel. Building a kernel from scratch forces you to understand low-level hardware interactions, assembly context switching, and memory layout. It fundamentally transforms you into a better embedded firmware engineer, sharpens your low-level debugging skills (hello, hard fault handlers!), and gives you complete freedom to architect a system tailored to your exact specifications. How to Get Started If you've decided to embark on building your own RTOS, here are the three critical decisions you need to make first: 1. Target Instruction Set Architecture (ISA) You need to choose a target architecture—common choices include ARM Cortex-M, RISC-V, MIPS, or x86. I chose the ARM Cortex-M4 architecture. It provides dedicated features tailored for OS design—such as the NVIC (Nested Vectored Interrupt Controller) , SysTick Timer , and the PendSV interrupt for safe context switching—along with an incredible community and ecosystem for developers. 2. Hardware vs. Simulation Select a development board featuring your target architecture (e.g., STM32). Alternatively, you can use QEMU to simulate the hardware environment before flashing physical silicon. In fact, many professional RTOS teams rely heavily on QEMU for automated testing and rapid prototyping. 3. Toolchain & Build Setup If you aren't using a Hardware Abstraction Layer (HAL) and want to write bare-metal code, you'll need a cross-compiler toolchain. Because I'm writing it in C and assembly for ARM, I am using the arm-none-eabi-gcc toolchain alongside GNU Make/CMake. What’s Next? In the next post, we’ll dive into startup scripts, linker scripts, and setting up the vector table . (Note: Throughout this series, I’ll be moving forward with the ARM Cortex-M4 setup, but the core operating system concepts will apply
AI 资讯
Building a Real Time Sports Scoring Engine with WebSockets and DynamoDB Streams
The Problem Sports scoring sounds simple. One team scores a point, the number goes up, everyone sees it. But when you build it as a web application that needs to work on courtside tablets, spectator phones, and wall mounted displays simultaneously, with voice commands and tap controls, the architecture becomes more interesting. The project was Scoring AI, a voice enabled match scoring application for sports courts. Players start a match, share a link, and control the scoreboard from any device. The backend handles real time state synchronization, optimistic locking, idempotent score updates, rate limiting, and WebSocket broadcasting. The team was small. Me and a coworker who handled the CI/CD side. We were at the same level, both full stack, and we designed the system together. He focused on the deployment pipeline and infrastructure automation. I focused on the application layer, the real time system, and the frontend. But the architecture decisions were shared. This article covers the technical decisions we made and how patterns from previous projects influenced them. Why DynamoDB for Live Matches The match scoring data is different from the business data around it. A match lasts about an hour, gets updated frequently, and needs to be read by many viewers at once. After the match is complete, it is archived and rarely accessed. I had seen what happens when you put high frequency state updates into a relational database on a previous project. Row locks, contention, connection pool exhaustion. For Scoring AI, we used DynamoDB for the live match state and PostgreSQL for everything else. The hot path needed fast writes, optimistic locking, and automatic cleanup of abandoned matches. DynamoDB provides all of these. The version field on each match record acts as an optimistic lock. Every score update is a conditional write that checks the version has not changed. The cold path uses PostgreSQL through Kysely for user profiles, subscriptions, pricing plans, payment histor
AI 资讯
PostgreSQL LISTEN/NOTIFY for Real-Time Multi-Tenant Events: Ditching Polling and WebSocket Complexity
PostgreSQL LISTEN/NOTIFY for Real-Time Multi-Tenant Events: Ditching Polling and WebSocket Complexity I've shipped real-time features in CitizenApp using three different approaches: naive polling (embarrassing), Redis pub/sub (overkill), and now PostgreSQL's native LISTEN/NOTIFY. The third option is what I should have started with. Most teams reach for Redis or RabbitMQ the moment they need real-time updates. It's the conventional wisdom. But here's the truth: if you're already running PostgreSQL, you have a battle-tested pub/sub system sitting right there. It handles multi-tenancy correctly, scales to thousands of concurrent connections, and eliminates an entire infrastructure dependency—which matters when you're deploying to Render or Vercel where every added service is friction. Why LISTEN/NOTIFY beats the alternatives Polling is dead. HTTP requests every 2-5 seconds for "new notifications"? That's technical debt masquerading as simplicity. It wastes bandwidth, kills your database with unnecessary queries, and users see stale data. Redis is powerful but expensive. Not just in dollars—in operational overhead. You need to manage connection pools, handle failover, monitor memory usage, and keep another service running in production. At CitizenApp's scale (thousands of concurrent tenants), we were paying $50/month for Redis on top of Render just to broadcast notifications that PostgreSQL could handle natively. WebSockets without a broker are a nightmare. If you're running multiple FastAPI workers (and you should be), a WebSocket connection to Worker A doesn't know about events published by Worker B. You need a message broker to fan-out events across processes. Unless you use PostgreSQL LISTEN/NOTIFY, which handles that automatically. PostgreSQL's pub/sub is: Transactional. Notifications only fire after a transaction commits. Tenant-aware. Use channel names like tenant_123_notifications and broadcast only to the right subscribers. Zero extra infrastructure. It's part