diff --git a/.optimize-cache.json b/.optimize-cache.json index 02c057507a..c4f8d41848 100644 --- a/.optimize-cache.json +++ b/.optimize-cache.json @@ -355,6 +355,7 @@ "static/images/blog/arena-june-2026-update/arena-leaderboard-without-skills.png": "f164ccde7cad0a8316104fea77d841b3b08d453b31489e00b383c1275b25e885", "static/images/blog/arena-june-2026-update/arena-opus-4-8-detail.png": "4008cb53a904cdf919f0fe7bf8820f6c9b6f46892c6fdda3ea7157633eb89b85", "static/images/blog/arena-june-2026-update/cover.png": "e6f5d1d1f405a7bf42499cec7a8044ef80ac7d5dc83ae81a3cdfaa5bd5913023", + "static/images/blog/asynchronous-vs-synchronous-programming/cover.png": "05f7cafd56a818c9a1719e719eac9dc370e9332f04086e78f162b3843f12966e", "static/images/blog/avif-in-storage/cover.png": "23c26ec1a8f23f5bf6c55b19407d0738aa41cdc502dc3eef14a78f430a14447b", "static/images/blog/avoid-backend-overengineering/cover.png": "c586c235dd6d3f992980748ec7b15cd3411edefe2e71dffc080840540f6d3ba3", "static/images/blog/baa-explained/cover.png": "a7b144c7549498760cc2bfddda186b8182766ef72e308abc637dc4cbb5a2c853", @@ -1271,8 +1272,10 @@ "static/images/blog/what-is-ciam/cover.png": "45a5261ae1bb8a38777f60a21ea60426c0832e3d58bf3164100548400d388ce1", "static/images/blog/what-is-cicd-a-complete-guide-for-developers/cover.png": "7abddce55b1467188faab83abd58189173bf9aba84de3d9f28fff0be8c6e9276", "static/images/blog/what-is-cloud-storage-an-expert-guide-for-developers/cover.png": "b7f545dbe9334d60f214e748ddfcea47484530a97f30ecf579d064a053c2821d", + "static/images/blog/what-is-crud-explained/cover.png": "8fd6708a0fb92bcfd5cbf91dcde7630585abd9e97dbbe7d6577b32202675fbf3", "static/images/blog/what-is-docker-a-simple-guide-for-developers/cover.png": "acd9c50ad749fcf676dd58b38cc6bbffba913bf5d817c6b725bd2c305088689e", "static/images/blog/what-is-kubernetes-an-expert-guide-for-developers/cover.png": "a7601f375841b143d62511fe3bbfb4bacb6989ddc56613f772b7dcd3d5e90688", + "static/images/blog/what-is-mcp-a-complete-guide-for-developers/cover.png": "71734bd04b81de2617eb12d2ffb58781092fa2ab970626c748e263d31a9a8866", "static/images/blog/what-is-mcp/claude-mcp-chat.png": "26842cfebca3ec2cec89448e1c0d7ddb3f5421cc57acdb8780d48d30a54cad82", "static/images/blog/what-is-mcp/claude-mcp-tools.png": "3a5ae700867b8671b5c9e3af61b094aeb64611168463db66ff440e0d427ac6bc", "static/images/blog/what-is-mcp/cover.png": "dc4537990c91d6f1768c5ab8775e5c52239eb901b15e2e74fce8b5a018855c32", diff --git a/src/routes/blog/post/asynchronous-vs-synchronous-programming/+page.markdoc b/src/routes/blog/post/asynchronous-vs-synchronous-programming/+page.markdoc new file mode 100644 index 0000000000..e454e18dd4 --- /dev/null +++ b/src/routes/blog/post/asynchronous-vs-synchronous-programming/+page.markdoc @@ -0,0 +1,156 @@ +--- +layout: post +title: Asynchronous vs. Synchronous programming +description: Learn the difference between synchronous and asynchronous programming, how blocking and non-blocking code works, and when developers should use each. +date: 2026-07-16 +cover: /images/blog/asynchronous-vs-synchronous-programming/cover.avif +timeToRead: 5 +author: aditya-oberai +category: best-practices +featured: false +unlisted: true +faqs: + - question: Does asynchronous programming use multiple threads? + answer: Not necessarily. Some runtimes use threads, but environments such as JavaScript commonly use an event loop to coordinate asynchronous operations without running application code on multiple threads simultaneously. + - question: What is the difference between synchronous and asynchronous APIs? + answer: A synchronous API call makes the caller wait until the operation finishes and returns a result. An asynchronous API call usually returns immediately while the operation continues in the background. + - question: Is asynchronous programming faster than synchronous programming? + answer: Async does not make an individual operation faster. It improves responsiveness and throughput by preventing the program from sitting idle while waiting for network requests, database queries, or file operations. + - question: When should I use asynchronous programming? + answer: Use asynchronous programming for I/O-bound work such as API calls, database queries, file access, background jobs, and other operations that spend time waiting on external systems. + - question: When should I use synchronous programming? + answer: Use synchronous programming for quick calculations, startup tasks, simple scripts, and operations that must run in a strict order. It is often easier to read, test, and debug. +--- +Most performance problems in application code come down to one decision made early and rarely revisited: whether a piece of work runs synchronously or asynchronously. Get it wrong and a single slow network call freezes your entire request, your UI stops responding, and your server sits idle waiting on I/O it could have handled in parallel. + +The confusing part is that synchronous and asynchronous code often look almost identical. The difference is not in the syntax, it is in what happens while the work is in progress. This post breaks down synchronous vs asynchronous programming, explains how blocking and non-blocking execution actually work, and gives you a clear rule for when to reach for each. + +# What is synchronous programming? + +**Synchronous programming runs one task at a time, in order, and each task must finish before the next one starts.** The program blocks on each line until it returns a result, then moves on. + +Think of it like a single checkout line at a store. Each customer is served completely before the next one steps forward. If one customer needs a price check that takes two minutes, everyone behind them waits, even if they only have one item. + +Here is synchronous code in JavaScript: + +```javascript +const data = readFileSync('config.json'); // blocks until the file is read +const parsed = JSON.parse(data); // only runs after the read finishes +console.log(parsed); // only runs after parsing +``` + +Each line waits for the one before it. This is predictable and easy to reason about, which is exactly why it is the default mental model most developers start with. The cost shows up when one of those lines involves waiting on something slow. + +# What is asynchronous programming? + +**Asynchronous programming lets a task start and then hand control back to the program while it waits, so other work can run in the meantime.** When the task completes, the program is notified and picks up where it left off. + +Back to the store analogy: instead of blocking the line, the customer needing a price check steps aside, the cashier serves everyone else, and the first customer returns once the price is confirmed. Nobody sits idle. + +Here is the asynchronous version of the same file read: + +```javascript +const data = await readFile('config.json'); // starts the read, frees the thread +const parsed = JSON.parse(data); // runs when the read resolves +console.log(parsed); +``` + +The `await` keyword makes this read like sequential code, but under the hood the runtime is free to do other work while the file is being read. That distinction is the whole point. + +# Blocking vs non-blocking: the real distinction + +People often use "synchronous" and "blocking" interchangeably, but they describe slightly different things. + +* **Blocking** means the current thread cannot do anything else until the operation completes. It is stuck. +* **Non-blocking** means the operation returns control immediately, and the result arrives later through a callback, promise, or event. + +Synchronous code is almost always blocking. Asynchronous code is designed to be non-blocking. The reason this matters is CPU utilization. A blocked thread waiting on a database query is doing nothing useful, it is just occupying memory and a slot in your thread pool. A non-blocking model lets that same thread serve other requests while the query runs. + +This is why a single-threaded runtime like Node.js can handle thousands of concurrent connections. It is not doing many things at once on the CPU, it is refusing to sit still while waiting on I/O. + +# Synchronous vs asynchronous programming: key differences + +Here is the comparison at a glance. + +| Aspect | Synchronous | Asynchronous | +| --------------- | ------------------------------- | ----------------------------------------------- | +| Execution order | Strictly sequential | Tasks can overlap and complete out of order | +| Thread behavior | Blocks while waiting | Frees the thread while waiting | +| Complexity | Simple to read and debug | Harder to trace, needs care with error handling | +| Best for | CPU-bound and short tasks | I/O-bound and long-running tasks | +| Failure impact | One slow call stalls everything | A slow call runs in the background | +| Typical tools | Plain function calls | Promises, async/await, callbacks, events | + +The short version: synchronous code trades throughput for simplicity, and asynchronous code trades simplicity for throughput. + +# How asynchronous code works under the hood + +Asynchronous programming is not magic, and it usually does not mean multithreading. In JavaScript and many other runtimes, it is built on an **event loop**. + +When you start an async operation, the runtime offloads it (to the operating system, a thread pool, or a network layer) and registers a callback. Your code keeps running. The event loop continuously checks whether any offloaded work has finished, and when it has, it queues the callback to run as soon as the call stack is clear. + +This model is well documented if you want to go deeper. The [MDN guide to the event loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Event_loop) explains the concurrency model in the browser, and the [Node.js event loop documentation](https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick) covers how it works on the server. + +The practical takeaway: async does not make individual operations faster. A network request takes the same amount of time either way. What async does is stop that request from wasting the time of everything else. + +# When to use synchronous programming + +Reach for synchronous code when the work is fast, CPU-bound, or when order and simplicity matter more than throughput. + +* **CPU-bound computation.** Sorting an array, transforming data in memory, or running a calculation does not wait on external systems, so making it async adds overhead with no benefit. +* **Startup and configuration.** Reading a config file once at boot is fine to do synchronously, since nothing else needs to run yet. +* **Scripts and simple tools.** A one-off migration script or CLI command is easier to write and debug as straight-line synchronous code. +* **Strict ordering.** When step two genuinely cannot begin until step one is fully done, synchronous flow expresses that intent clearly. + +The rule of thumb: if the operation does not wait on I/O and finishes quickly, synchronous is the right default. + +# When to use asynchronous programming + +Reach for asynchronous code whenever a task waits on something outside your process. + +* **Network requests.** API calls, database queries, and third-party service calls all involve waiting. Blocking on them wastes your server's capacity. +* **File and disk operations.** Reading, writing, and streaming files are I/O-bound and benefit from non-blocking execution. +* **User interfaces.** In a browser or mobile app, blocking the main thread freezes the UI. Async keeps the interface responsive while data loads. +* **Long-running background jobs.** Sending emails, processing uploads, generating reports, or running batch operations should not make the caller wait. +* **High-concurrency servers.** If you need to serve many simultaneous requests, non-blocking I/O is what lets a small number of threads handle a large number of connections. + +If you are building an application backend, most of your meaningful work is I/O-bound, which means asynchronous execution is usually the correct default there. + +# Common asynchronous programming mistakes + +Async gives you throughput, but it introduces failure modes that synchronous code does not have. Watch for these. + +* **Forgetting to await.** An un-awaited promise runs, but your code moves on without its result, leading to race conditions and silent failures. +* **Unhandled rejections.** Errors in async code do not always propagate the way you expect. Wrap awaited calls in try/catch or attach a `.catch()`. +* **Accidental serialization.** Awaiting calls one after another when they could run together wastes the whole benefit. Use `Promise.all` to run independent operations concurrently. +* **Blocking the event loop.** Running heavy CPU work inside an async runtime still blocks everything, because there is only one thread handling the loop. Offload it to a worker or a background function. + +# Handling synchronous and asynchronous work with Appwrite + +Once you move this decision from a single function into a real backend, you need infrastructure that supports both models cleanly. [Appwrite Functions](/docs/products/functions) is built around exactly this distinction. + +When you [execute a function](/docs/products/functions/execute), you choose the mode explicitly. A **synchronous execution** makes the caller wait for the result and is capped at a 30-second timeout, which suits API endpoints and short tasks where you need the response immediately. An **asynchronous execution** returns an execution ID right away and runs the work in the background, which suits long-running jobs like batch processing, email delivery, or upload post-processing. + +```javascript +const execution = await functions.createExecution({ + functionId: '', + async: true, // returns immediately, runs in the background +}); +``` + +Beyond Functions, the same non-blocking philosophy runs through the platform. [Appwrite Realtime](/docs/apis/realtime) pushes updates to clients over subscriptions instead of forcing them to poll, and [Appwrite Messaging](/docs/products/messaging) handles email, SMS, and push delivery as background work so your request path stays fast. Together they let you keep user-facing calls synchronous and responsive while heavy work happens asynchronously out of the critical path. + +To go deeper on structuring this well, read the [complete guide to Appwrite Functions](/blog/post/appwrite-functions-guide) for triggers and execution modes, and [serverless functions best practices](/blog/post/serverless-functions-best-practices) for patterns that keep async work reliable in production. + +# Getting started with Appwrite Functions + +Choosing between synchronous and asynchronous execution is not about picking a favorite. It is about matching the model to the work: synchronous for fast, CPU-bound, order-dependent tasks, and asynchronous for anything that waits on I/O or runs long. Get that mapping right and both your servers and your users stop waiting on work that never needed to block them. + +The fastest way to see it in practice is to deploy a function and try both execution modes yourself. + +* [Appwrite Functions overview](/docs/products/functions) +* [Execute a function synchronously or asynchronously](/docs/products/functions/execute) +* [Function runtimes](/docs/products/functions/runtimes) +* [A complete guide to Appwrite Functions](/blog/post/appwrite-functions-guide) +* [Serverless functions best practices](/blog/post/serverless-functions-best-practices) +* [Join the Appwrite Discord community](https://appwrite.io/discord) \ No newline at end of file diff --git a/src/routes/blog/post/what-is-mcp-a-complete-guide-for-developers/+page.markdoc b/src/routes/blog/post/what-is-mcp-a-complete-guide-for-developers/+page.markdoc new file mode 100644 index 0000000000..32e48ad1bb --- /dev/null +++ b/src/routes/blog/post/what-is-mcp-a-complete-guide-for-developers/+page.markdoc @@ -0,0 +1,126 @@ +--- +layout: post +title: What is MCP? A complete guide for developers +description: Learn what MCP is, how Model Context Protocol works, its architecture, tools, resources, prompts, APIs, and how developers can start building with it. +date: 2026-07-16 +cover: /images/blog/what-is-mcp-a-complete-guide-for-developers/cover.avif +timeToRead: 5 +author: aditya-oberai +category: ai +featured: false +unlisted: true +faqs: + - question: What is the difference between an MCP client and an MCP server? + answer: An MCP client connects an AI application to one MCP server and manages communication with it. The server exposes the tools, resources, and prompts that the AI application can use. + - question: What is the difference between MCP and an API? + answer: An API defines how software interacts with a particular service. MCP provides a standard way for AI applications to discover and use many tools, often by placing an MCP server in front of existing APIs. MCP complements APIs rather than replacing them. + - question: Do I need an MCP server to use MCP? + answer: You need access to an MCP server, but you do not always need to build one yourself. You can connect an existing server to a compatible AI client or create your own when exposing a custom product, API, or internal data source. + - question: Is MCP secure? + answer: MCP can support authorization for remote HTTP servers, but connecting a server still gives an AI application access to potentially sensitive tools and data. Developers should use narrowly scoped credentials, validate inputs, require approval for sensitive actions, and only connect trusted servers. +--- +AI models are good at reasoning and terrible at acting. Ask one to summarize your latest report, check today's database entries, or open a pull request, and it stalls. It has no way to reach your files, your database, or your APIs. It can only work with what was in its training data. + +For a while, the fix was custom integrations: write glue code for every tool, handle each authentication scheme, and rewrite it all when an API changes. That does not scale. **Model Context Protocol (MCP)** is the standard that replaces those one-off integrations with a single, shared interface. + +This guide covers what MCP is, how its architecture and primitives work, the transports it runs over, and how you can start building with it today. + +# What is MCP (Model Context Protocol)? + +MCP is an open protocol that defines how AI applications connect to external tools, data sources, and APIs through a uniform interface. Instead of teaching a model a new integration for every service, you expose your capabilities through an **MCP server**, and any MCP-compatible client can use them. + +MCP was developed by [Anthropic](https://www.anthropic.com/news/model-context-protocol) and released as an open standard in November 2024. It has since been adopted across IDE assistants, desktop clients, and backend platforms, and the specification is maintained openly at [modelcontextprotocol.io](https://modelcontextprotocol.io). + +The short version: MCP turns a model that can only think into one that can fetch real data and trigger real actions, without you writing bespoke plumbing for each connection. + +# Why MCP exists: The integration problem + +The problem MCP solves is combinatorial. If you have **M** AI applications and **N** tools, connecting them directly means building and maintaining M × N integrations. Every new tool multiplies the work, and every API change breaks something downstream. + +MCP collapses that to **M + N**. Each tool ships one MCP server, each AI application speaks MCP once, and the two sides interoperate without knowing anything specific about each other. You build the integration once and it works everywhere. + +This is the same shift the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) brought to code editors. Before LSP, every editor needed custom support for every language. After it, one language server worked in any compatible editor. MCP applies that pattern to AI applications and the tools they need to reach. + +# How MCP works: Architecture + +MCP uses a client-server architecture with three roles. Understanding the split is the key to reasoning about how everything connects. + +* **Host**: The AI application the user interacts with, such as Claude Desktop, Cursor, or VS Code. The host manages one or more clients. +* **Client**: A connector that lives inside the host and maintains a dedicated one-to-one connection to a single server. +* **Server**: A program that exposes capabilities (tools, data, and prompts) over MCP. A GitHub server exposes repo operations, a database server exposes queries, and so on. + +A single host can run many clients at once, each connected to a different server. That is how one assistant can pull errors from Sentry, read commits from GitHub, and write to your backend in the same conversation, with each server handling only its own domain. + +Under the hood, MCP is built on [JSON-RPC 2.0](https://www.jsonrpc.org/specification). Clients and servers exchange structured request and response messages, and the connection begins with an initialization handshake where both sides declare which features they support. + +# MCP primitives: Tools, resources, and prompts + +MCP servers expose their capabilities through three primitives. Knowing which one to reach for is most of what you need to design a good server. + +* **Tools** are executable functions the model can call to perform an action: run a query, send a message, create a record. Tools are model-controlled, meaning the AI decides when to invoke them based on the task. +* **Resources** are read-only data the server makes available for context: files, database rows, documentation, or API responses. Resources are application-controlled and give the model something to reason over. +* **Prompts** are reusable, templated instructions that a server offers to standardize common workflows. Prompts are typically user-controlled, surfaced as slash commands or menu options in the client. + +The distinction matters in practice. A weather server might expose a `get_forecast` **tool** for live lookups, a **resource** listing saved locations, and a **prompt** that formats a daily briefing. Each primitive has a different trigger and a different level of control. + +Clients contribute their own primitives back to servers, including **sampling** (letting a server request a model completion), **roots** (scoping which files or directories a server may access), and **elicitation** (asking the user for input mid-task). Together these keep the human and the model in the loop rather than handing servers unchecked access. + +# MCP transports and APIs + +MCP defines two standard transports for how clients and servers actually talk to each other. + +* **stdio**: The server runs as a local subprocess and communicates over standard input and output. This is the simplest and most common setup for local tools, since credentials never leave your machine. +* **Streamable HTTP**: The server runs as a remote service reachable over HTTP, with support for streaming responses. This is the transport for hosted servers and replaced the earlier HTTP with Server-Sent Events approach. + +Because MCP standardizes the message format above the transport, the same server logic works whether it runs locally over stdio or remotely over HTTP. You write your tool and resource handlers once, then choose how to deploy. + +# MCP vs REST APIs: What is the difference? + +A common question is whether MCP is just another API. It is not, and the difference is about layers. + +A REST API is one specific contract for one specific service. MCP is a protocol layer above that. It defines how an AI client discovers available tools, inspects their input schemas, and calls them in a consistent way, regardless of what sits underneath. The MCP server still talks to the real REST APIs and databases. The model only has to learn MCP once instead of learning every API individually. + +In other words, REST answers "how do I call this one service," while MCP answers "how does an AI application discover and use any tool that has been exposed to it." They are complementary, not competing. + +# What can you do with MCP? + +MCP is already in production across everyday developer workflows, not just demos. A few concrete examples: + +* **AI-assisted coding.** Editors like Cursor, Zed, and VS Code connect to servers that read your repo, check recent commits, and query your backend, so the assistant reasons over real project context instead of guessing. +* **Debugging and operations.** An assistant can pull recent errors from a Sentry server, cross-reference the failing deployment on a Vercel server, and inspect the offending commit on GitHub, all in one thread. +* **Internal knowledge and data.** Teams expose sales figures, inventory, or customer records through a server so employees can ask questions in plain language and get answers backed by live data. +* **Backend management.** With a server for your cloud platform, an agent can create users, run migrations, and deploy functions without you leaving the chat. + +The common thread is that each of these used to require custom integration work. MCP makes the capability portable across every client that speaks the protocol. + +# How to start building with MCP + +You do not need to implement the protocol by hand. The MCP project ships official [SDKs](https://modelcontextprotocol.io/docs/sdk) for TypeScript, Python, and other languages that handle the JSON-RPC layer, the handshake, and the transport for you. Building a server usually comes down to declaring your tools, resources, and prompts and wiring them to real logic. + +If you are using MCP rather than authoring a server, the workflow is simpler: pick a client, point it at a server, and start prompting. The client handles discovery and tool calls automatically. + +Two good ways to get hands-on: + +* **Use existing servers.** Attach servers for the tools you already work with. Our roundup of the [best MCP servers and clients](/blog/post/10-best-mcp-server-client) is a good starting point for what is available. +* **Connect your backend.** If you build on Appwrite, the [Appwrite MCP server](/docs/tooling/ai/mcp-servers/api) exposes your project to any MCP-compatible client so an AI agent can manage [Databases](/docs/products/databases), create users through [Auth](/docs/products/auth), upload files to [Storage](/docs/products/storage), and deploy [Functions](/docs/products/functions) directly from a chat. + +# MCP security best practices + +MCP itself is just the protocol; security depends entirely on how a server is configured and what credentials it holds. Treat every MCP server like a privileged backend service. + +Scope API keys to the minimum permissions the task needs, prefer local stdio servers when you want credentials to stay on your machine, and use staging projects for exploratory work. Before connecting any server, audit which tools it exposes. An MCP server is only as safe as the access you hand it. + +# Getting started with the Appwrite MCP server + +MCP is the layer that lets AI applications actually do things instead of only describing them. Once you understand the architecture, the three primitives, and the transports, most servers become predictable to reason about and straightforward to build. + +The fastest way to see it in action is to connect your own backend. The Appwrite MCP server exposes your entire project to AI coding agents through a compact two-tool architecture, so you can create users, query databases, and deploy functions from within Claude Code, Cursor, or any MCP client. Read [how we rebuilt it in MCP Server 2.0](/blog/post/announcing-appwrite-mcp-server-2), then follow the docs to add it to your setup. + +# Resources + +* [Appwrite MCP server documentation](/docs/tooling/ai/mcp-servers/api) +* [Appwrite Docs MCP server](/docs/tooling/ai/mcp-servers/docs) +* [What exactly is MCP, and why is it trending?](/blog/post/what-is-mcp) +* [10 awesome MCP servers and clients for developers](/blog/post/10-best-mcp-server-client) +* [Official MCP specification](https://modelcontextprotocol.io) +* [Join the Appwrite Discord community](https://appwrite.io/discord) \ No newline at end of file diff --git a/static/images/blog/asynchronous-vs-synchronous-programming/cover.avif b/static/images/blog/asynchronous-vs-synchronous-programming/cover.avif new file mode 100644 index 0000000000..13cce2d262 Binary files /dev/null and b/static/images/blog/asynchronous-vs-synchronous-programming/cover.avif differ diff --git a/static/images/blog/what-is-mcp-a-complete-guide-for-developers/cover.avif b/static/images/blog/what-is-mcp-a-complete-guide-for-developers/cover.avif new file mode 100644 index 0000000000..3d2375d312 Binary files /dev/null and b/static/images/blog/what-is-mcp-a-complete-guide-for-developers/cover.avif differ