diff --git a/src/routes/blog/post/how-to-avoid-framework-fatigue-when-building-backends/+page.markdoc b/src/routes/blog/post/how-to-avoid-framework-fatigue-when-building-backends/+page.markdoc new file mode 100644 index 00000000000..f980cc46364 --- /dev/null +++ b/src/routes/blog/post/how-to-avoid-framework-fatigue-when-building-backends/+page.markdoc @@ -0,0 +1,119 @@ +--- +layout: post +title: How to avoid "framework fatigue" when building backends +description: Avoid framework fatigue when building backends. Learn how to choose stable tools, reduce stack complexity, and ship faster without constantly switching frameworks. +date: 2026-04-09 +cover: /images/blog/how-to-avoid-framework-fatigue-when-building-backends/cover.avif +timeToRead: 5 +author: aditya-oberai +category: best-practices +featured: false +unlisted: true +faqs: + - question: 'What is framework fatigue in backend development?' + answer: "Framework fatigue is the pattern of repeatedly evaluating, switching, or second-guessing backend frameworks instead of shipping product. It's driven by a fast-moving ecosystem where new frameworks launch constantly, each promising better performance or cleaner syntax. The result is developers spend more time researching stacks than building features." + - question: 'How long should I spend evaluating a backend framework before committing?' + answer: 'For most projects, one week is enough. Set a hard deadline, shortlist two or three frameworks with proven production track records, build a small prototype in each, and pick one. Open-ended evaluation almost always costs more than picking a "good enough" framework and shipping.' + - question: 'Should I switch backend frameworks when a new one launches?' + answer: 'Not unless your current framework is causing a concrete, measurable problem in production. New frameworks usually improve on narrow dimensions, but switching mid-project means rewriting integrations, retraining your team, and delaying user feedback. Migrate based on evidence, not announcements.' + - question: "What's the difference between a backend framework and a backend platform?" + answer: 'A backend framework (like Express, Fastify, or Hono) handles HTTP routing, middleware, and request/response shaping. A backend platform (like Appwrite) handles infrastructure concerns such as authentication, databases, file storage, and serverless functions. Frameworks are about how you write request handlers; platforms are about which problems you no longer have to solve yourself.' + - question: 'How do I know if my backend stack is too complex?' + answer: "A useful test: can you explain how data moves from a request to the database and back in under five minutes? If not, the architecture has more layers than the stage of the project warrants. Complexity should match the problem you're solving, not the stack trends you're following." + - question: 'Does framework fatigue affect solo developers and small teams?' + answer: "Yes, often more severely. Solo developers don't have teammates to push back on stack changes, so the cost of churn is absorbed entirely by one person. Small teams suffer from constant re-onboarding, where every framework switch effectively resets the team's shared mental model of the codebase." + - question: 'What should I prioritize when choosing a backend framework in 2026?' + answer: "Prioritize stability, ecosystem maturity, and operational simplicity over raw performance benchmarks. A framework that's slightly slower but actively maintained, well-documented, and easy to deploy will outperform a faster framework that breaks between versions or lacks community support." + - question: 'How does using a backend platform reduce framework fatigue?' + answer: "When authentication, databases, storage, and functions are handled by a platform with a stable API, the framework decision becomes much smaller. You're no longer choosing an entire stack, just an HTTP layer. That makes it easier to commit, easier to migrate later if needed, and easier to focus development time on product logic instead of infrastructure plumbing." +--- + +You start a new backend project. You spend the first week researching frameworks. Express or Fastify? Hono or Elysia? Do you need an ORM, and if so, which one? Should you go serverless? And wait, someone just posted that this new framework is "production-ready" and does everything in half the code. + +You haven't written a single line of product logic yet. + +This is framework fatigue, and it's not just an inconvenience. It's a pattern that quietly drains developer time, delays shipping, and makes perfectly good projects feel perpetually unfinished. + +# Why framework fatigue happens to backend developers + +The backend ecosystem moves fast. New frameworks ship weekly, each promising better performance, a cleaner API, or a simpler mental model. For developers who care about their craft, staying current feels like professional responsibility. + +The problem is that evaluating frameworks isn't free. Every hour spent comparing benchmarks, reading GitHub discussions, and scaffolding test projects is an hour not spent building. And the cycle tends to repeat: new project, new research phase, new stack decision. + +Frontend developers face this too, but backend fatigue has a specific character. Backend decisions affect data integrity, security, and scalability, so the stakes feel higher. That makes it easier to justify another round of research before committing. + +# The real cost of framework churn + +The direct cost is obvious: time you could have spent shipping. But the compounding costs are worse. + +- **Shallow expertise accumulates.** When you keep switching frameworks, you never go deep on any of them. You learn enough to start but not enough to handle edge cases, tune performance, or diagnose subtle bugs. +- **Every switch carries hidden migration work.** Switching frameworks mid-project means rewriting integration code, updating tests, and debugging inconsistencies that only show up at runtime. That work rarely fits neatly into a sprint. +- **Churn signals instability to your team.** If you're working with other developers, constant stack changes mean constant re-onboarding. What feels like iteration to you feels like chaos to someone joining the project. +- **You delay the feedback that matters.** The only feedback loop that actually validates your backend decisions is real users interacting with a shipped product. Anything that delays shipping delays learning. + +# How to recognize you're in the fatigue loop + +Framework fatigue doesn't always look like paralysis. Sometimes it looks like productivity: + +- You're reading documentation instead of writing code. +- You're building proof-of-concept projects that never evolve into real ones. +- You're refactoring a working backend because something newer launched. +- You feel uncomfortable committing to a stack without exploring "just one more option." + +The signal to watch for: if your research phase consistently outlasts your building phase, the stack is not the problem. The decision process is. + +# What actually matters when choosing a backend framework + +Most backend framework comparisons focus on performance benchmarks and syntax preferences. Those matter less than developers think. Here's what actually matters for long-term decisions: + +**Stability and maintenance trajectory.** Is this framework actively maintained? Has it made breaking changes repeatedly? A fast framework with an unstable API will cost you more in migration work than a slower one with a reliable release cycle. + +**Ecosystem maturity.** Can you find answers to your problems without opening a GitHub issue? Mature ecosystems have libraries for common problems, answered Stack Overflow threads, and examples that match your use case. + +**How much it solves vs. how much it delegates.** Some frameworks give you routing and middleware and leave everything else to you. Others include more of the stack. Neither is inherently better, but you need to know what you're signing up for. A minimal framework with a long list of integration decisions is only a good choice if you genuinely want to own those decisions. + +**Operational complexity.** The backend doesn't just need to work locally. It needs to deploy, scale, and be debuggable in production. Frameworks that are elegant to write but painful to operate are a bad tradeoff for most teams. + +# The simplest way to break the cycle + +Stop treating the framework decision as a research problem and treat it as an engineering constraint. + +Pick a framework with a proven track record for your use case and set a time limit on evaluation. One week of research, a decision, then ship. If the framework causes a concrete problem in production, migrate with evidence. Not because something newer launched. + +More importantly: separate the framework from the infrastructure. Most backend framework debates conflate two different things. The framework handles request routing, middleware, and response shaping. The infrastructure handles authentication, data persistence, file storage, and background jobs. You can swap frameworks more easily if your infrastructure isn't also tangled up in framework-specific code. + +This is where a unified backend platform changes the decision surface significantly. When auth, databases, storage, and functions are handled by a platform with a stable API, the framework choice becomes much less load-bearing. You're not choosing between frameworks, you're choosing between HTTP request handlers. + +# How to choose a backend stack you'll actually stick with + +A backend stack you'll stick with has a few properties: + +- **Handles solved problems with solved solutions.** Authentication, file storage, and database access are not competitive advantages. Using a proven platform for these frees you to build what actually differentiates your product. +- **Small enough to understand completely.** You should be able to hold the full architecture in your head. If you can't explain how data moves through your backend in five minutes, it's too complex for the stage you're at. +- **Consistent enough to reuse.** The best backends are boring. The same patterns, the same primitives, the same conventions across every feature. Consistency is what makes a team fast. + +# Simplify your backend with Appwrite + +Appwrite is an open-source developer infrastructure platform for building web, mobile, and AI apps. It provides [authentication](/docs/products/auth), [databases](/docs/products/databases), [file storage](/docs/products/storage), [serverless functions](/docs/products/functions), real-time subscriptions, and messaging in a single platform. Appwrite is available as a managed service through [Appwrite Cloud](https://cloud.appwrite.io) or self-hosted on any Docker-compatible infrastructure. + +For developers dealing with framework fatigue, Appwrite addresses the root cause: too many separate decisions. + +- **Authentication is built in.** Email/password, OAuth2, phone, magic URLs, and MFA are ready out of the box. No auth library to choose, no session management to implement. +- **Databases with a query API.** Create collections, define your schema, and query immediately. No separate ORM decision, no API layer to build around your data model. +- **Storage without S3 configuration.** File upload, compression, image transformation, and access controls are included. No policies to configure, no upload URL generation logic. +- **Functions for server-side logic.** When you need processing that belongs on the server, Appwrite Functions run without a separate server to maintain or deploy. + +The result is a backend stack where the infrastructure decisions are already made. Your framework choice becomes simple: use whatever HTTP library you prefer for your application layer, and delegate the solved problems to a platform that handles them correctly. + +# Getting started with a simpler backend stack + +Framework fatigue is a solvable problem. The solution is not finding the perfect framework. It's reducing the number of decisions that need to be made in the first place. + +Pick one framework. Give it a fair trial on a real project. Delegate infrastructure to a proven platform. Ship something. The feedback you get from a real product will tell you more about what to optimize than any benchmark comparison. + +Explore how Appwrite simplifies backend infrastructure decisions: + +- [Appwrite Authentication docs](/docs/products/auth) +- [Appwrite Databases docs](/docs/products/databases) +- [Appwrite Functions docs](/docs/products/functions) +- [Sign up for Appwrite Cloud](https://cloud.appwrite.io) diff --git a/src/routes/blog/post/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works/+page.markdoc b/src/routes/blog/post/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works/+page.markdoc new file mode 100644 index 00000000000..5fd429d3047 --- /dev/null +++ b/src/routes/blog/post/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works/+page.markdoc @@ -0,0 +1,126 @@ +--- +layout: post +title: How to build and ship a side project alone +description: Build and ship a side project alone using a backend stack that actually works. Learn how to choose the right tools, simplify infrastructure, and launch faster without managing multiple services. +date: 2026-04-09 +cover: /images/blog/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works/cover.avif +timeToRead: 5 +author: aditya-oberai +category: startup +featured: false +unlisted: true +faqs: + - question: "What's the fastest backend stack for a solo developer's side project?" + answer: 'The fastest stack is one that minimizes setup decisions. A unified backend platform that bundles authentication, database, file storage, and serverless functions into a single SDK is faster to ship with than stitching together separate services. The fewer dashboards, accounts, and integrations you manage, the more time you spend on actual product features.' + - question: 'Should I build authentication from scratch for a side project?' + answer: 'No. Building auth from scratch is the most common reason solo side projects stall. Sessions, refresh tokens, OAuth2 callbacks, password hashing, and MFA each have edge cases that take days to handle correctly. Use a managed authentication service so you can focus on the parts of your product that are genuinely unique.' + - question: 'Do I need microservices for a side project?' + answer: 'No. Microservices solve coordination problems for large engineering teams, not technical problems for solo developers. A single application backed by a unified platform is easier to build, debug, and deploy. Stick with a monolith until you have real users and a real bottleneck.' + - question: 'How much backend infrastructure do I actually need before launching?' + answer: 'Most side projects need only five things: user authentication, structured data storage, file uploads, occasional background or scheduled logic, and frontend hosting. Anything beyond that, including caching layers, message queues, and separate microservices, can wait until you have paying users.' + - question: 'Is it worth using a Backend-as-a-Service (BaaS) for a side project?' + answer: 'For most solo developers, yes. A BaaS removes the infrastructure decisions that consume the first few weekends of a new project. The trade-off is some loss of low-level control, which rarely matters at the side-project stage. If you later need full control, an open-source BaaS like Appwrite can be self-hosted, so the migration path stays open.' + - question: 'When should I use serverless functions vs. direct database access?' + answer: 'Use serverless functions for background jobs, scheduled tasks, webhooks, and business logic that must run server-side. Use direct database access through the SDK for straightforward reads and writes from your client. Replacing every API call with a function adds deployment complexity without adding product value.' + - question: "How do I avoid over-engineering my side project's backend?" + answer: "Set a rule: don't optimize for scale you don't have yet. Skip microservices, custom auth, managed Kubernetes, and elaborate caching until a real bottleneck appears. The goal of a side project is to validate whether anyone wants what you're building. Premature optimization delays that answer." + - question: "What's the best way to host the frontend for a side project?" + answer: 'Host it on the same platform as your backend if possible. Keeping frontend and backend in one console reduces context switching, simplifies environment management, and removes the overhead of monitoring multiple dashboards. Git-based deployments with automatic preview environments on pull requests are the lightweight workflow most solo developers want.' + - question: 'Will a unified backend platform lock me in?' + answer: 'Not if you choose an open-source one. With a platform like Appwrite, you can self-host the exact same stack on your own infrastructure using Docker if pricing or policies change. That makes the migration path real instead.' +--- + +Solo developers don't stall because they can't code. They stall because they burn through momentum on infrastructure before writing a single line of product logic. + +You spend the first weekend setting up authentication middleware, the second wiring up file uploads to S3, and the third debugging CORS errors. By the time the backend is technically ready, the idea feels stale and the energy is gone. + +The problem is not that backend work is hard. It's that most solo developers copy enterprise-grade stack decisions that don't match the constraints of a one-person project. Here's how to avoid that and actually ship. + +# Why most solo side projects never ship + +The most common culprit is **infrastructure sprawl**. Five different services, five accounts, five billing dashboards, five sets of API keys. Each one adds a decision point. Each integration is another potential failure. + +Enterprise setups make sense when you have a dedicated SRE team and engineers per layer. For a solo developer, that overhead kills the project. + +Your real goal before the first user signs in: reduce the number of decisions you have to make. + +# Define what your backend actually needs + +Before picking any tool, write down what your backend has to do. For most side projects, this list is shorter than you think: + +- Authenticate users +- Store and query structured data +- Handle file uploads +- Run background or scheduled logic +- Serve the frontend + +That's the full scope for a working MVP. Anything not on this list should wait until you have paying users. If you're tempted to add a message queue, a caching layer, or separate microservices before you have 10 users, stop and come back to the list. + +# Authentication: use a service, not a library + +Building auth from scratch is the single most common mistake solo developers make. Even if you've done it before, getting sessions, refresh tokens, OAuth2 callbacks, password hashing, and MFA right takes days, not hours. Those days are better spent on your actual product. + +[Appwrite Authentication](/docs/products/auth) handles email and password, magic links, phone OTP, and 30+ OAuth2 providers including Google, GitHub, and Discord. You get session management, rate limiting, and MFA without writing a single auth handler. If you need to connect to an existing identity system, custom token support lets you bridge that gap without rebuilding everything. + +The trade-off is the same one you make with any managed service: you're trusting the provider's implementation. For auth specifically, that trade-off is almost always worth it. + +# Database: close to your app, easy to query + +The SQL vs. NoSQL debate doesn't matter at the side project stage. What matters is that your database is easy to set up, close to your application, and not something you have to maintain yourself. + +[Appwrite Databases](/docs/products/databases) gives you a relational database with support for complex queries, relationships, and real-time subscriptions. You build the schema from the console or through the API and query it without writing raw SQL. + +Appwrite scales along with your usage, so you can focus on shipping features instead of capacity planning early on. + +# File storage: don't configure S3 manually + +At some point your app will need to store files: avatars, user uploads, exports. Setting up an S3 bucket, configuring IAM roles, writing upload handlers, and serving files with signed URLs is half a day of work that adds zero product value. + +[Appwrite Storage](/docs/products/storage) handles uploads, access control, image transformations, and file previews out of the box. Upload a file, get a URL back, and move on to building the actual feature. + +# Serverless functions: pick the right jobs for them + +Functions are where solo developers over-engineer the most. Spinning up a functions-heavy architecture on day one means debugging cold starts and deployment pipelines before shipping a single user-facing feature. + +Use [Appwrite Functions](/docs/products/functions) for a specific set of jobs: + +- Background tasks like sending emails or processing uploads +- Scheduled operations like data sync or cleanup +- Webhooks for handling Stripe events or third-party callbacks +- Custom business logic that doesn't belong on the client + +Don't replace your entire API with functions. If you're doing straightforward data access, let the database handle it directly through the SDK. Functions are for cases where you need server-side control, not for everything. + +# Frontend hosting: keep it in the same platform as your backend + +Hosting is often an afterthought until it becomes a problem. You've built the backend, and now you need to deploy a Next.js or SvelteKit app somewhere that handles SSR, runs CI/CD from Git, and doesn't require you to manage a VPS. + +[Appwrite Sites](/docs/products/sites) lets you deploy your frontend directly from a Git repository. You get automatic preview deployments on pull requests and production deployments on merge. Managing backend and frontend in the same platform cuts down context switching and reduces the number of dashboards you have to watch. + +# Why a unified backend platform ships faster than a multi-service setup + +When every backend service comes from a different vendor, you pay in cognitive overhead: multiple dashboards, separate billing, different SDK upgrade cycles, and stitching together logs across systems just to debug one request. + +A platform like Appwrite keeps auth, database, storage, functions, and hosting under one roof. One SDK, one console, one account. For a solo developer, that consolidation is not just a convenience. It's the difference between shipping and not shipping. + +Appwrite is also open source. If pricing changes or you decide to self-host later, you can run the exact same stack on your own infrastructure with Docker. That's a real migration path, not a hypothetical one. + +# Avoid optimizing for scale you don't have yet + +The other mistake solo developers make is picking technologies for 100,000 users on day one. Microservices, separate auth providers, managed Kubernetes clusters. That's what large companies use because they have large problems. You don't yet. + +Ship the simplest version that works. Upgrade the parts that actually bottleneck you, when they bottleneck you. The goal of a side project is to find out whether anyone wants what you're building. A 10ms database query difference does not matter when you have zero users. + +If you're weighing a BaaS against building your own custom backend, the trade-offs are covered in detail here: [BaaS vs. custom backend](/blog/post/baas-vs-custom-backend). + +# Start building your side project with Appwrite + +Appwrite gives solo developers and indie hackers a backend that covers auth, database, storage, functions, and hosting in one place. There's a generous free tier to get started, and if your project grows into something serious, the [Appwrite Startups Program](/startups) offers cloud credits and priority support to help you scale without rebuilding your stack. + +- [Appwrite quick start](/docs/quick-starts) +- [Appwrite Authentication](/docs/products/auth) +- [Appwrite Databases](/docs/products/databases) +- [Appwrite Storage](/docs/products/storage) +- [Appwrite Functions](/docs/products/functions) +- [Appwrite Sites](/docs/products/sites) +- [BaaS vs. custom backend](/blog/post/baas-vs-custom-backend) diff --git a/src/routes/blog/post/the-mental-model-every-developer-needs-for-backend-architecture/+page.markdoc b/src/routes/blog/post/the-mental-model-every-developer-needs-for-backend-architecture/+page.markdoc new file mode 100644 index 00000000000..30e4a42c61e --- /dev/null +++ b/src/routes/blog/post/the-mental-model-every-developer-needs-for-backend-architecture/+page.markdoc @@ -0,0 +1,141 @@ +--- +layout: post +title: The mental model every developer needs for backend architecture +description: A practical mental model for backend architecture that helps developers design scalable systems, reduce complexity, and choose the right backend components with confidence. +date: 2026-04-09 +cover: /images/blog/the-mental-model-every-developer-needs-for-backend-architecture/cover.avif +timeToRead: 5 +author: atharva +category: architecture +featured: false +unlisted: true +faqs: + - question: 'What is a backend architecture mental model?' + answer: 'A backend architecture mental model is a simplified way of thinking about how the parts of a backend fit together. It helps developers decide where logic should live, which storage layer to use, and how requests flow through the system. A good mental model reduces decision fatigue and makes design choices feel obvious instead of arbitrary.' + - question: "What's the difference between authentication and authorization?" + answer: 'Authentication answers "who are you?" by verifying a user''s identity through credentials, tokens, or OAuth providers. Authorization answers "what are you allowed to do?" by checking permissions and roles for that user. Treating them as a single concept leads to permission checks scattered throughout the codebase, which is a common source of security bugs.' + - question: 'Why should business logic be separated from data access?' + answer: 'Mixing business logic with database queries means a schema change can break business rules, and a business rule change forces query rewrites. Separating them lets each evolve independently. The cleanest pattern is functions that make decisions calling a thin data-access layer that only reads and writes. Logic decides, storage remembers.' + - question: 'When should I use serverless functions instead of API routes?' + answer: "Use serverless functions for work that should not block a user's request: sending transactional emails, processing uploaded files, running scheduled cleanups, or reacting to events like sign-ups. Use API routes for synchronous operations the user is actively waiting on. Functions are asynchronous workers, not a replacement for your entire API." + - question: 'What kind of data belongs in a database vs. file storage vs. a cache?' + answer: "Use a database for structured data you query frequently, like users, orders, and posts. Use file storage for binary content like images, PDFs, and videos. Use a cache for data that's read often and tolerates being slightly stale, like session tokens or computed results. Storing files as database blobs or caching data that needs strong consistency are two of the most common mistakes." + - question: 'How do I know if my backend has clear boundaries?' + answer: "A clean boundary is a contract: defined inputs, defined outputs, no shared internals. The test is whether you can change what's inside a service or module without breaking anything outside it. If Service A reads directly from Service B's database table, the boundary is broken even if B's API is untouched. The same rule applies within a monolith." + - question: "Do I need to follow this mental model if I'm building a small app?" + answer: "Yes, and arguably more so. Small apps grow into messy ones precisely because boundaries weren't defined early. The mental model isn't about adding complexity; it's about putting code in predictable places so the project stays maintainable as it grows. Skipping it doesn't save time, it just defers the cost." + - question: 'What questions should I answer before starting a new backend feature?' + answer: "Before writing code, answer five questions: What does the user want to do? Who's allowed to do it? What needs to happen? What needs to be stored, and where? What happens after? These map directly to your API surface, auth rules, business logic, storage layer, and background functions. Most architectural debt comes from skipping one of these." + - question: 'How does Appwrite map to a clean backend architecture?' + answer: 'Each Appwrite product maps to a layer in the mental model: Auth handles the authentication layer, Databases handle structured persistence, Storage handles binary files, Functions handle event-driven and scheduled work, and Messaging handles outbound notifications. Using a unified platform means the boundaries between layers are already enforced by the SDK rather than something you have to design from scratch.' +--- + +Most junior developers don't struggle with writing code. They struggle with knowing _where_ the code should go. + +You know what authentication is. You know what a database does. But when you sit down to build a feature, the questions pile up fast. Where does this logic live? Should this be a function or an API route? Why does my service know too much about my database? + +That fog doesn't come from not knowing enough. It comes from not having a mental model that makes the pieces click together. + +Here's one that works. + +# Think of every backend request as a pipeline + +The simplest way to reason about backend architecture is to see every incoming request as data flowing through a pipeline: + +**Receive → Authenticate → Validate → Process → Persist → Respond** + +Each stage has one job. When you mix them, you get code that is hard to test, hard to change, and hard to debug. + +- **Receive:** The API layer accepts the request and routes it. +- **Authenticate:** Check who the user is before anything else happens. +- **Validate:** Confirm the input is what you expect. Reject early. +- **Process:** Apply business logic. This is the only stage that makes decisions. +- **Persist:** Write results to a database, file store, or cache. +- **Respond:** Return a consistent result to the caller. + +When something breaks, ask: which stage failed? That question alone will cut your debugging time in half. + +# Separate what your app knows from what it remembers + +Here is the most common mistake junior developers make: mixing business logic with data access. + +**Business logic** is your app's understanding of the world. It answers questions like "Can this user post to this channel?" or "Is this order eligible for a refund?" **Data access** is just reading and writing. It does not make decisions. + +When these two are tangled, a schema change in your database breaks business rules. A business rule change forces you to rewrite queries. Separate them, and you can change either independently. + +In practice, write functions that contain your decisions and keep your database queries in a separate layer that those functions call. The rule is simple: logic decides, storage remembers. + +# Know which storage layer to use + +Not all data is alike. Reaching for the wrong storage type is one of the most common sources of performance and architectural problems. + +- **Databases:** For structured data you query often. User records, orders, posts. Use this for anything with relationships or filtering requirements. +- **File storage:** For binary content. Images, PDFs, videos. Do not store files as blobs in a database row. +- **Cache:** For data you read frequently but that can tolerate being slightly stale. Session tokens, computed results, rate limit counters. +- **Message queue or event bus:** For work that should not happen inside the request cycle. Sending emails, processing uploads, triggering webhooks. + +When you reach for a database to store a file, or try to query a file for an attribute, step back and ask: what kind of data is this? The answer determines where it lives. + +[Appwrite Storage](/docs/products/storage) handles file uploads, encryption, access controls, and image transformations so you are not building that infrastructure from scratch. + +# Auth is a layer, not a feature + +Authentication and authorization are not the same thing, and treating them as a single "auth system" creates problems. + +**Authentication** answers: who are you? **Authorization** answers: what are you allowed to do? + +Auth should be a layer that wraps your entire API, not something bolted onto individual routes. Decide early what claims a token carries, such as user ID, roles, and permissions. Then let every other layer in your system trust those claims without re-checking them. + +If you find yourself querying the database to check permissions inside a business logic function, that is a sign your auth layer is not doing enough work. Push that logic up to where requests enter the system. + +[Appwrite Auth](/docs/products/auth) supports email/password, OAuth2, phone OTP, magic links, and more. User claims are available to every request, without extra round trips to the database. + +# Functions handle what your API should not wait for + +Serverless functions are often treated as another way to write API routes. That is not where they are most useful. + +Functions are for code that runs: + +- After an event, such as user sign-up, file upload, or document change +- On a schedule, like sending a daily digest or cleaning up expired records +- In the background, without blocking the user's request + +If a user clicks "Submit" and has to wait three seconds while your API sends a transactional email, that is the wrong design. The API should respond immediately and pass the email job to a function or queue. Functions are asynchronous workers. They handle the side effects your API does not have time for. + +[Appwrite Functions](/docs/products/functions) supports event-based triggers across auth, databases, storage, and messaging, so you can wire up side effects without building custom infrastructure. + +# Define boundaries before you write implementations + +Whether you are building a monolith or splitting things into services, one rule applies everywhere: **define your contracts before your code.** + +A boundary is a contract. It says: this is the input I accept, and this is the output I produce. When services communicate through clear contracts (REST, events, RPC), you can change what is inside the boundary without breaking what is outside. + +The mistake is letting services reach into each other's internals. When Service A reads directly from Service B's database table, you have coupled them at the data layer. Changing B's schema breaks A, even if B's own API is unchanged. + +This applies within a monolith too. A function that reaches directly into your database from the middle of a route handler has no boundary. Give your layers explicit interfaces and the rest is much easier to reason about. + +# Map your backend before you build it + +When starting a new feature or project, run through these five questions before writing a line of code: + +1. **What does the user want to do?** This defines your API surface. +2. **Who is allowed to do it?** This defines your auth rules. +3. **What needs to happen?** This is your business logic. +4. **What needs to be stored, and where?** This picks your storage layer. +5. **What happens after?** This defines your functions and events. + +Answer all five before touching the keyboard. You will spend less time refactoring and more time shipping. Most architectural debt starts with skipping one of these questions. + +For a deeper look at how these pieces come together in practice when shipping a product end to end, see [how to build and ship a side project alone](/blog/post/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works). + +# Getting started with backend architecture on Appwrite + +If you want a backend that already handles the layers you would otherwise build from scratch, Appwrite gives you a solid starting point. Each product maps directly to a layer in the mental model above. + +- [Appwrite Auth](/docs/products/auth) for authentication across multiple providers and methods +- [Appwrite Databases](/docs/products/databases) for structured data storage, querying, and relationships +- [Appwrite Storage](/docs/products/storage) for file uploads, access control, and image transformations +- [Appwrite Functions](/docs/products/functions) for event-driven and scheduled background logic +- [Appwrite Messaging](/docs/products/messaging) for push notifications, SMS, and email + +You can use all of these together or adopt only the parts that fill gaps in your current stack. There is no lock-in, and you can self-host if the managed cloud does not fit your requirements. diff --git a/static/images/avatars/steven.avif b/static/images/avatars/steven.avif index da682f880bb..594a205820b 100644 Binary files a/static/images/avatars/steven.avif and b/static/images/avatars/steven.avif differ diff --git a/static/images/avatars/steven.png b/static/images/avatars/steven.png deleted file mode 100644 index d675ab70cc3..00000000000 Binary files a/static/images/avatars/steven.png and /dev/null differ diff --git a/static/images/blog/how-to-avoid-framework-fatigue-when-building-backends/cover.avif b/static/images/blog/how-to-avoid-framework-fatigue-when-building-backends/cover.avif new file mode 100644 index 00000000000..e4d2f33b4ec Binary files /dev/null and b/static/images/blog/how-to-avoid-framework-fatigue-when-building-backends/cover.avif differ diff --git a/static/images/blog/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works/cover.avif b/static/images/blog/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works/cover.avif new file mode 100644 index 00000000000..c69ea166e8a Binary files /dev/null and b/static/images/blog/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works/cover.avif differ diff --git a/static/images/blog/the-mental-model-every-developer-needs-for-backend-architecture/cover.avif b/static/images/blog/the-mental-model-every-developer-needs-for-backend-architecture/cover.avif new file mode 100644 index 00000000000..24b19244ba8 Binary files /dev/null and b/static/images/blog/the-mental-model-every-developer-needs-for-backend-architecture/cover.avif differ diff --git a/static/images/community/avatars/1.avif b/static/images/community/avatars/1.avif index ce0bc7a4048..3f95cd9c318 100644 Binary files a/static/images/community/avatars/1.avif and b/static/images/community/avatars/1.avif differ diff --git a/static/images/community/avatars/1.png b/static/images/community/avatars/1.png deleted file mode 100644 index 04762eaaae2..00000000000 Binary files a/static/images/community/avatars/1.png and /dev/null differ diff --git a/static/images/community/avatars/2.avif b/static/images/community/avatars/2.avif index 563e2543937..cc235f0636e 100644 Binary files a/static/images/community/avatars/2.avif and b/static/images/community/avatars/2.avif differ diff --git a/static/images/community/avatars/2.png b/static/images/community/avatars/2.png deleted file mode 100644 index a0a470d4382..00000000000 Binary files a/static/images/community/avatars/2.png and /dev/null differ diff --git a/static/images/community/avatars/3.avif b/static/images/community/avatars/3.avif index c2b71d08d90..b4fefd78f46 100644 Binary files a/static/images/community/avatars/3.avif and b/static/images/community/avatars/3.avif differ diff --git a/static/images/community/avatars/3.png b/static/images/community/avatars/3.png deleted file mode 100644 index f2c8b3aea9d..00000000000 Binary files a/static/images/community/avatars/3.png and /dev/null differ diff --git a/static/images/community/avatars/4.avif b/static/images/community/avatars/4.avif index 0909a01c859..5610e3a8cc5 100644 Binary files a/static/images/community/avatars/4.avif and b/static/images/community/avatars/4.avif differ diff --git a/static/images/community/avatars/4.png b/static/images/community/avatars/4.png deleted file mode 100644 index 8e1371cd341..00000000000 Binary files a/static/images/community/avatars/4.png and /dev/null differ diff --git a/static/images/community/avatars/5.avif b/static/images/community/avatars/5.avif index 80db8c775f7..abb8981e38c 100644 Binary files a/static/images/community/avatars/5.avif and b/static/images/community/avatars/5.avif differ diff --git a/static/images/community/avatars/5.png b/static/images/community/avatars/5.png deleted file mode 100644 index 7c7c7c8904d..00000000000 Binary files a/static/images/community/avatars/5.png and /dev/null differ diff --git a/static/images/community/avatars/6.avif b/static/images/community/avatars/6.avif index 5924af43908..fa0722d271c 100644 Binary files a/static/images/community/avatars/6.avif and b/static/images/community/avatars/6.avif differ diff --git a/static/images/community/avatars/6.png b/static/images/community/avatars/6.png deleted file mode 100644 index e6f5051762f..00000000000 Binary files a/static/images/community/avatars/6.png and /dev/null differ diff --git a/static/images/community/avatars/walter.avif b/static/images/community/avatars/walter.avif index afbc45753fd..36f58ba9d7b 100644 Binary files a/static/images/community/avatars/walter.avif and b/static/images/community/avatars/walter.avif differ diff --git a/static/images/community/avatars/walter.png b/static/images/community/avatars/walter.png deleted file mode 100644 index 3e45483c58a..00000000000 Binary files a/static/images/community/avatars/walter.png and /dev/null differ