今日已更新 344 条资讯 | 累计 37249 条内容
关于我们

标签:#architecture

找到 724 篇相关文章

产品设计

Mini book: Architecture as a Socio-Technical Craft

Architecture is not a fixed choice made once; fitness is a moving target driven by changing regulations, tech, and markets. Even a sound design can silently stop fitting over time without bad calls. Spanning seven articles on context stores, gateways, and topologies, this collection treats architecture as an evolving sociotechnical craft where teams deliberately shape friction, fitness, and flow. By InfoQ

2026-08-21 原文 →
AI 资讯

AWS Serverless Patterns and Anti-Patterns: What Works, What Breaks, and When to Use What

Serverless on AWS isn't "just use Lambda." It's a design philosophy: let AWS manage the infrastructure, pay only for what you use, and build with managed services that scale independently. But the patterns that work in serverless are fundamentally different from traditional architectures — and the anti-patterns are expensive to learn the hard way. This guide covers the patterns that work in production, the anti-patterns that waste money or cause outages, and the decision framework for when serverless is the right (or wrong) choice. The Serverless Building Blocks ┌─────────────────────────────────────────────────────────────────────┐ │ AWS SERVERLESS STACK │ ├─────────────────────────────────────────────────────────────────────┤ │ COMPUTE │ Lambda | Fargate (serverless containers) │ │ API │ API Gateway (REST/HTTP/WebSocket) | AppSync (GraphQL)│ │ ORCHESTRATION │ Step Functions | EventBridge Scheduler │ │ MESSAGING │ SQS | SNS | EventBridge │ │ STORAGE │ S3 | DynamoDB | Aurora Serverless │ │ STREAMING │ Kinesis | DynamoDB Streams | MSK Serverless │ │ AUTH │ Cognito | IAM | Lambda Authorizers │ │ OBSERVABILITY │ CloudWatch | X-Ray | Application Signals │ └─────────────────────────────────────────────────────────────────────┘ Key principle: In serverless, you compose applications from managed services. Lambda is the glue between them — not the application itself. Pattern 1: Synchronous API (Request/Response) The most common serverless pattern: HTTP API backed by Lambda. Client → API Gateway → Lambda → DynamoDB / Aurora Serverless │ Response ← ─ ─ ─ ─ ─ ─ ┘ Best Practices API Gateway HTTP API (not REST API) — cheaper, faster, simpler for most cases One Lambda per route (single responsibility) — not a monolith Lambda Keep Lambda warm — use Provisioned Concurrency for latency-sensitive endpoints DynamoDB for simple access patterns — scales with traffic, no connection pooling Aurora Serverless v2 for complex queries — but use RDS Proxy to manage connections When to Choose H

2026-08-21 原文 →
AI 资讯

A Quality Gate for Node.js SaaS Text Summarization Chat APIs

Choose a text-summary API by the percentage of outputs that pass a source-grounded evaluation, then compare latency, regional controls, and cost only among the candidates that clear that bar. For a JavaScript subscription app serving US and EU users, the decisive constraint is rarely the cheapest advertised token rate. It is the complete production path: cleaning an article, fitting or splitting it, generating a summary, validating claims, and recovering safely when a request is interrupted. Short answer: use a narrow internal completion interface, test it with representative long documents, and keep the provider choice behind an adapter. A direct hosted endpoint is the simpler default for one approved backend. Add a self-hosted gateway only when routing, policy enforcement, or repeated provider comparisons justify another service to operate. I start this kind of decision in a notebook, but I don't stop at a few outputs that sound good. Fluent summaries can omit the one qualification that changes an article's meaning. The useful unit of comparison is an accepted summary, not a successful API response. What should a US and EU text summary API evaluation measure? Define acceptance before sending the first request. For a long article, I usually want a short abstract, the central claims, preserved numbers, and explicit uncertainty where the source is uncertain. Those fields form an output contract. The evaluator then asks whether each claim is supported by the input and whether any required idea disappeared. Build the corpus from document shapes the product expects: clean prose, copied navigation, tables flattened into text, repeated paragraphs, empty sections, contradictory statements, and inputs near the application's size limit. Keep a held-out slice for release decisions. Otherwise prompt tuning turns the evaluation set into a memory test. The regional review belongs beside quality, but it answers a different question. An API being reachable from Europe does not est

2026-08-21 原文 →
AI 资讯

AWS SNS and Dedicated SMS APIs for Critical Node.js Alert Delivery

An e-commerce alert is not complete when an API accepts a message. It is complete when the application records a terminal delivery state, suppresses an invalid recipient, or escalates through a separately governed channel. Short answer: use a dedicated SMS API for a small critical-alert worker when template ownership and direct status control matter; keep AWS SNS when SMS belongs inside an existing cloud messaging stack, and prefer a callback-capable provider when escalation must begin in under a minute. That choice creates work. A direct API keeps the send path narrow, but polling, retries, dead-letter handling, and country-specific fallback rules remain application responsibilities. For critical alerts, those responsibilities need the same idempotency and audit discipline as a ledger entry: one intent, one durable identifier, and an append-only record of every state observation. No provider turns carrier delivery into exactly-once delivery. Implement the template control plane in Node.js Start with the contract, not the vendor. The application owns an immutable alert intent containing the business event ID, recipient, template version, jurisdiction, and escalation deadline. Template ownership is the decision axis: if compliance reviewers must approve and reproduce the exact text that was sent, keep the canonical template version in the application and treat a provider template ID as deployment metadata. If a provider must own localization or regulatory registration, record that provider template ID beside the application version rather than letting it become invisible configuration. A useful state machine separates accepted from a terminal delivery result. Persist the provider message ID after the initial send, schedule periodic status reads, and append each observation with its timestamp and request ID. A retry after HTTP 429 is transport recovery, not permission to create a second alert; honor Retry-After , use exponential backoff, and preserve the same idempote

2026-08-21 原文 →
AI 资讯

Serverless: When It Helps and When It Hurts

The Allure of Serverless Serverless computing, despite its name, still runs on servers. The difference is that you don't manage them. You deploy functions, and the cloud provider handles scaling, patching, and availability. The promise is simple: you focus on code, not infrastructure. That's genuinely appealing for many projects, but it's not a silver bullet. Let's talk about when serverless shines and when it becomes a headache. When Serverless Helps 1. Spiky and Unpredictable Traffic Serverless scales automatically. If you have a sudden surge of users, functions spin up to handle the load, then scale down to zero when idle. You pay only for what you use. This is ideal for APIs with variable traffic, like a mobile app backend that sees daily peaks and quiet nights. For example, a simple REST endpoint using AWS Lambda and API Gateway: exports . handler = async ( event ) => { const body = JSON . parse ( event . body ); // process request return { statusCode : 200 , headers : { ' Content-Type ' : ' application/json ' }, body : JSON . stringify ({ message : `Hello, ${ body . name } !` }) }; }; No server to configure, no load balancer to set up. It just works. 2. Event-Driven Workloads Serverless excels at reacting to events: file uploads, database changes, messages in a queue. You can glue services together with minimal code. For instance, resizing an image when it's uploaded to S3: import boto3 from PIL import Image import os s3 = boto3 . client ( ' s3 ' ) def handler ( event , context ): bucket = event [ ' Records ' ][ 0 ][ ' s3 ' ][ ' bucket ' ][ ' name ' ] key = event [ ' Records ' ][ 0 ][ ' s3 ' ][ ' object ' ][ ' key ' ] download_path = ' /tmp/ ' + key upload_path = ' /tmp/resized- ' + key s3 . download_file ( bucket , key , download_path ) with Image . open ( download_path ) as img : img . thumbnail (( 200 , 200 )) img . save ( upload_path ) s3 . upload_file ( upload_path , bucket , ' resized/ ' + key ) This is a perfect serverless use case: short-lived, statele

2026-08-21 原文 →
AI 资讯

Node.js Welcome Flow Explained — Custom-Domain Email API Suppression, DKIM, Polling

Short answer: for a healthtech marketplace seller alert, choose an email API with custom-domain DKIM, a pre-send suppression check, and an event list that a scheduled job can poll. Keep the notification outside the order transaction. This design fits a standard US/EU SaaS workflow when delayed delivery status is acceptable; if delivery events must drive application state within seconds, choose a webhook-capable provider instead. The decision is mostly about integration effort, but counting SDK setup hours is too narrow. Count the controls the team will still own after launch: credentials, domain gates, retry identity, callback ingress, poll cursors, retention, and vendor-specific telemetry. A short integration can leave a long operational tail. This record covers a transactional notice that tells a marketplace seller about a new order. It does not establish that clinical data belongs in the message, or that a provider satisfies a regulated workload. I'm not sure an API feature matrix can answer those questions; current contracts, residency terms, and a review of the actual message fields would. How does a US/EU SaaS welcome email API handle custom domain DKIM and suppression? The order and its notification need different state machines. Committing an order is a business event. Checking suppression, submitting email, and later observing delivery are communication work. If those concerns share one transaction, a slow provider call can hold the order path open, while a retry can blur the difference between “the order exists” and “the seller was notified.” Use four invariants to evaluate every candidate. First, a suppressed or opted-out address never reaches the send step. Second, production mail is enabled only after the custom domain is verified and DKIM is managed. Third, every retry refers to the same logical seller-order notification. Fourth, processing the same polled event twice cannot repeat an application state change. Those rules are deliberately boring. They

2026-08-21 原文 →
AI 资讯

Buying a phone number is a distributed transaction

The API makes it look trivial. const number = await carrier . numbers . buy ({ phone_number : " +1... " }); await db . insert ( " rented_numbers " , { user_id , e164 : number . phone_number }); await stripe . subscriptions . create ({ customer , price }); Three lines, one number, done. Ship it. What you actually wrote is a distributed transaction across three systems. They share no transaction log, they have no two-phase commit, and none of them can roll back the others. The carrier will keep charging you for a number your database has never heard of. Stripe will stop charging for a number your database still thinks is paid up. Neither one is going to mention it. I run a virtual phone number product. Below are the failure modes that actually cost us money, roughly in order of how much. The orphan taxonomy Write down the states first, because the interesting ones are the states nobody designs for. Three systems, each holding an opinion about a single number: Your DB Carrier Stripe What is actually happening active owns it active The happy path. Rare in the tail. no row owns it nothing You pay monthly rent on a number nobody can see or use. active released active You bill a customer for a number you no longer own. pending_cancellation owns it canceled Customer stopped paying. You are still paying the carrier. active owns it canceled You provide service for free, indefinitely. cancelled owns it canceled Release failed at teardown. Silent monthly bleed. Every row under the first one is reachable from a plain network timeout at a bad moment. The first orphan class is the worst, because you cannot see it from inside your own product. No row, no user, no support ticket. The number sits in the carrier's inventory producing an invoice line every month until somebody actually reads the invoice. The second class is the one that generates a complaint. The rest leak money in one direction or the other, quietly. Reconcile, don't prevent The instinct is to armour the write path. S

2026-08-21 原文 →
AI 资讯

Clean code isn't what I thought it was

What working on real systems taught me about maintainable code. My second job was the first time I worked with an international team where everyone had ten or more years of experience. I had maybe two. It was also the first time I was part of proper code reviews, branching strategies, and pull request workflows. Everything felt new and slightly intimidating. One of my first tasks was adding spacing between two elements. It should have been a simple margin or padding change, but I added a <br> tag instead. The feedback on that PR was polite but clear, and it made me a little embarrassed. That moment, along with dozens of similar ones, made me want to get better. I started reading about clean code and caring deeply about how my code looked. Small functions, no repetition, everything abstracted and organized. For a while, that served me well. It helped me grow from a junior developer into someone who could write code that passed review without a wall of comments. But over time, as I worked on larger systems with real users and real constraints, I started noticing that the rules I had learned didn't always hold up. Sometimes the "clean" approach made things worse, and sometimes messy-looking code worked better than the elegant version I would have written. This post is about how my definition of clean code expanded. I still believe in the principles I learned early on. I'd just add a few things to them now. What I thought clean code meant When I first started paying attention to code quality, my idea of clean code was mostly about appearances. If the code looked organized and followed certain patterns, it was clean. If it didn't, it wasn't. I believed in small functions for everything. If a function was longer than fifteen or twenty lines, something was wrong. I would extract pieces into helpers even when they were only used once, just because the parent function felt "too long." I was strict about DRY. Any time I saw similar logic in two places, I would immediately pul

2026-08-21 原文 →
AI 资讯

IEC 104 Before the Wire: Understanding Its Architecture, Framing, and Security Boundaries

By RUGERO Tesla ( @404Saint ). IEC 60870-5-104 (IEC 104) is the TCP/IP-based member of the IEC 60870-5 telecontrol family. It was designed to carry SCADA telemetry and control information across packet-switched networks, particularly within electrical power systems. Before getting into raw packets, it is worth understanding how IEC 104 is structured, how its communication state is maintained, and where its security boundaries actually exist. This is the map before we meet the protocol on the wire. Protocol Stack IEC 104 operates over TCP, commonly using port 2404 . Two protocol components are particularly important: APCI : Application Protocol Control Information ASDU : Application Service Data Unit The APCI handles framing, sequencing, acknowledgments, and connection control. The ASDU carries the actual telecontrol information. +-------------------------------------------------------------+ | ASDU | | Type ID | VSQ | COT | CA | IOA | Information Objects | +-------------------------------------------------------------+ | APCI | | 0x68 | Length | Control 1 | Control 2 | Control 3 | Ctrl 4 | +-------------------------------------------------------------+ | TCP / IP | +-------------------------------------------------------------+ Every APDU begins with the 0x68 start byte, followed by a length field and four control bytes. The length represents the bytes following the length field, including the four control bytes and, when present, the ASDU. That fixed structure is the starting point for understanding IEC 104 traffic. I, S, and U Formats IEC 104 defines three APDU formats. I-Format: → I-format frames carry application information and therefore contain an ASDU. They also carry two sequence numbers: N(S) : send sequence number N(R) : receive sequence number These allow communicating stations to maintain ordered transmission and acknowledgment state. S-Format: → S-format frames are supervisory frames. They do not carry an ASDU. Their purpose is to communicate receive ac

2026-08-20 原文 →
开发者

LISKOV SUBSTITUTION PRINCIPLE

A parent class must be able to be substituted by its child classes without breaking the application. In practice, this helps to organize the idea of inheritance, as it prevents us from extending a parent class only to later remove an already implemented method or do a “throw new Error(‘Not implemented’)”. Making us much more careful during planning. THE BIGGEST SYMPTOM OF ERROR Unfortunately, it is a symptom that appears late, but it is exactly when we are going to make a new implementation. You realize you violated Liskov when you are going to build a class or subclass and need to purposely throw an error in the implementation of a method. Exactly because that method shouldn't be there, but it is. A BAD EXAMPLE For example, in a delivery system. In this case, the “Delivery” class should be the parent/base for the other implementations. But the ‘MotoboyDelivery’ class breaks this. Code Example: // BAD: The subclass breaks the parent class contract. class Delivery { public calculateShipping (): number { return 15.0 ; } public getTrackingCode (): string { return " TRK123456789 " ; } } class MotoboyDelivery extends Delivery { public calculateShipping (): number { return 8.0 ; } // ERROR! There is no tracking code. public getTrackingCode (): string { throw new Error ( " Motoboys do not have a tracking code. " ); } } THE SOLUTION For those who do not yet know the 'Liskov Substitution Principle', it might seem that fitting in a sequence of 'if's is the solution. But in reality, the ideal path is to rethink how this abstraction is built. A good guiding principle is to think that a child class must always be able to take the place of the parent, without breaking the application. A GOOD EXAMPLE Still in the delivery system. ‘Delivery’ now has ‘TrackableDelivery’ in the middle of the way. With this, each “leaf”/edge of the application inherits what makes the most sense and nothing is broken. Code Example: interface Delivery { calculateShipping (): number ; } interface Trackab

2026-08-20 原文 →
AI 资讯

PRINCÍPIO DA SUBSTITUIÇÃO DE LISKOV

Uma classe mãe deve ser capaz de ser substituída pelas suas classes filhas sem que a aplicação quebre. Isso na prática ajuda a organizar a ideia de herança, já que nos faz evitar estender uma classe mãe, apenas para depois remover um método já implementado ou fazer um “throw new Error(‘Not implemented’)”. Fazendo com que tenhamos mais cuidado no planejamento. O MAIOR SINTOMA DE ERRO Infelizmente é um sintoma que aparece de forma tardia, mas é justamente quando vamos fazer uma nova implementação. Você percebe que feriu o Liskov quando você vai construir uma classe ou subclasse e precisa lançar um erro proposital na implementação de um método. Justamente porque aquele método não deveria estar ali, mas está. UM EXEMPLO RUIM Por exemplo em um sistema de entregas. Nesse caso a classe “Delivery” deveria ser a mãe/base para as demais implementações. Mas a classe ‘MotoboyDelivery’ quebra isso. Exemplo de Código: // RUIM: A subclasse quebra o contrato da classe mãe. class Delivery { public calculateShipping (): number { return 15.0 ; } public getTrackingCode (): string { return " TRK123456789 " ; } } class MotoboyDelivery extends Delivery { public calculateShipping (): number { return 8.0 ; } // ERRO! Não tem código de rastreio. public getTrackingCode (): string { throw new Error ( " Motoboys não possuem código. " ); } } A SOLUÇÃO Para quem ainda não conhece o 'Liskov Substitution Principle', pode parecer que encaixar uma sequência de ifs é a solução. Mas na verdade o caminho ideal é repensar como essa abstração é construída. Um bom norte é pensar que uma classe filha sempre deve ser capaz de substituir o lugar da mãe, sem quebrar a aplicação. UM EXEMPLO BOM Ainda no sistema de entregas. ‘Delivery’ agora tem no meio do caminho ‘TrackableDelivery’. Com isso, cada “folha”/ponta da aplicação herda quem faz mais sentido e nada é quebrado. Exemplo de Código: interface Delivery { calculateShipping (): number ; } interface TrackableDelivery extends Delivery { getTrackingCode (): st

2026-08-20 原文 →
开发者

Designing CRM Workflows Like State Machines

Business workflows can look messy. A lead arrives from a website form. Someone contacts the customer. A follow-up is scheduled. A proposal is sent. The deal either moves forward or becomes inactive. But from a software design perspective, this process can be viewed in a much simpler way: A series of states and transitions. This is one reason CRM workflows can benefit from thinking like developers. Every Lead Has a State A lead is not just a row in a database. At any point in time, it has a current state. For example: NEW ↓ CONTACTED ↓ QUALIFIED ↓ PROPOSAL_SENT ↓ NEGOTIATION ↓ WON / LOST Each transition should represent a meaningful business event. This structure makes the workflow easier to understand and reduces ambiguity. Avoid Undefined Transitions Problems appear when teams can move records anywhere without clear rules. For example: NEW → WON Is that valid? Sometimes, maybe. But if a transition skips important steps, the system may lose useful context. A better workflow defines which transitions are expected: NEW → CONTACTED CONTACTED → QUALIFIED QUALIFIED → PROPOSAL_SENT PROPOSAL_SENT → NEGOTIATION NEGOTIATION → WON NEGOTIATION → LOST This doesn't mean every business needs a rigid process. It means the system should make state changes understandable. Events Can Trigger Actions State changes can also trigger workflows. For example: Event: Lead Created ↓ Assign Owner ↓ Create Follow-Up Task ↓ Notify Sales Team Or: Event: Proposal Sent ↓ Schedule Follow-Up ↓ Set Reminder ↓ Track Response This is where workflow automation becomes useful. Instead of expecting users to remember every repetitive step, the system can handle predictable actions. Separate State From History Current state tells you where something is now. History tells you how it got there. For example: Current State: NEGOTIATION That alone is useful. But an event history gives more context: Aug 10 → Lead Created Aug 11 → First Contact Aug 13 → Qualified Aug 16 → Proposal Sent Aug 19 → Negotiation Started

2026-08-20 原文 →
AI 资讯

WebMCP Agentic Web: Debugging 2‑Second Latency Spikes

webmcp agentic web: Why Backend Engineers Must Rethink Their Architecture Quick Answer webmcp agentic web: Agentic web workloads over MCP require stateless gateways, distributed context stores, prompt caching, and fine‑grained telemetry to keep latency below 350 ms and cost under control. Latency and State in Multi‑Agent LLMs When a Multi‑Agent System talks to an LLM over the Model Context Protocol (MCP) , the assumptions that hold for CRUD REST APIs break apart. A 200‑ms timeout that covers a simple GET request now collapses into a 2‑second latency spike because each tool call injects a new sub‑prompt, inflates the token budget, and forces the backend to stitch together dozens of partial contexts. In the field, the LLM behaves like a stateful, high‑throughput service that must be orchestrated, not a stateless function. Real‑World Example Consider a U.S. e‑commerce platform that needs to serve 12 k concurrent shopping sessions. Each session spawns up to five agents (pricing, inventory, recommendation, fraud, checkout). The platform’s existing micro‑service stack was built for single‑shot CRUD calls; when the agentic layer was added, the following issues surfaced: Context drift: stale prompts silently degraded recommendation quality. Token explosion: every tool call added 200–300 tokens, pushing the total payload past 8 k tokens. Throughput hit: the MCP service was throttled by Azure OpenAI’s per‑deployment request rate limits. After re‑architecting to a stateless MCP gateway backed by a distributed context store, the platform maintained 99th‑percentile latency under 350 ms even during a Black Friday surge. Trade‑Offs Aspect Option A Option B When to choose Context Storage Redis Cluster (in‑memory, low latency) Cosmos DB (strong consistency, global replication) Redis for ultra‑low latency, Cosmos for compliance or multi‑region writes Prompt Caching Enable KV‑cache on Azure OpenAI Re‑send system prompt on every request Enable when prompt size >20% of total token budge

2026-08-20 原文 →
AI 资讯

InfoQ Opens Enrollment for New AI-Assisted Engineering Online Certification Program

InfoQ has opened enrollment for the InfoQ Certified AI-Assisted Engineering Program, a five-week online certification program for senior engineers and architects who already run a coding agent against production code daily, where the open questions have moved past prompting into what the agent is allowed to touch and what catches its mistakes before a human does. By Artenisa Chatziou

2026-08-20 原文 →
AI 资讯

The Open-Sourcing of DeepSeek Harness Opens the Door to Modular, Unbundled AI Agent Infrastructure

DeepSeek has released a developer preview of DeepSeek Harness (dsh), an open-source execution runtime for building autonomous AI agents. The software features a micro-kernel architecture with modular plugins for various functional units. The release includes an append-only event logging system for tracking execution activities. Adoption may depend on plugin ecosystem stability and API maintenance. By Olimpiu Pop

2026-08-20 原文 →
AI 资讯

A practical guide to live streaming protocols, latency and scaling

Live video looks simple until you build it. Then you discover that "low latency" means five different things, that your CDN and your latency target are fighting each other, and that the box which handled ten viewers falls over at ten thousand for reasons nobody warned you about. This is the guide I wish existed when I started. No vendor talk, just how the pieces fit. 1. Ingest and delivery are separate decisions The single most common mistake is treating "streaming protocol" as one choice. It is two. Ingest is getting video from a camera, encoder or browser into your server. Delivery is getting it from your server to viewers. They have different constraints and you almost never use the same protocol for both. A typical stack ingests over RTMP or SRT and delivers over HLS. Another ingests WebRTC and delivers WebRTC. Mixing is normal and expected. Once you separate them, most of the confusion disappears. 2. The ingest protocols RTMP is old, TCP-based, and still everywhere. Every encoder speaks it, OBS defaults to it, and it just works. Latency is typically 2 to 5 seconds. Classic RTMP is limited to H.264 and AAC, though the Enhanced RTMP spec has added HEVC and AV1. Being TCP, it degrades badly on lossy networks: packet loss becomes head-of-line blocking, and your stream stalls instead of gracefully dropping quality. SRT is the answer to that. UDP-based with its own retransmission layer (ARQ), a configurable latency buffer, and built-in AES encryption. It is designed for pushing broadcast-quality video across the public internet, which is exactly where RTMP struggles. If your source is on a flaky connection, a 4G link, or a different continent, SRT is usually the right call. # Publishing over SRT with ffmpeg ffmpeg -re -i input.mp4 -c copy -f mpegts \ "srt://your-server:4200?streamid=live/stream1" RTSP is what IP cameras speak. If you are pulling from surveillance hardware, you are pulling RTSP whether you like it or not. WHIP (WebRTC-HTTP Ingestion Protocol) is the n

2026-08-19 原文 →