diff --git a/.optimize-cache.json b/.optimize-cache.json index ad33a498be..915ad29ad7 100644 --- a/.optimize-cache.json +++ b/.optimize-cache.json @@ -602,6 +602,8 @@ "images/blog/how-to-attract-users-to-open-source-project/swag-twitter.png": "b4f128cf606f0587d5eca29a13d9ad8eff8fadc94e7e4698c53d8f25133262b3", "images/blog/how-to-attract-users-to-open-source-project/tutorials.png": "89da3e654bf3de4b670d490ee51414798e8875ecef352bbca679beb054fd0896", "images/blog/how-to-attract-users-to-open-source-project/twitter-poll.png": "5ccf09d5a1ba425db7303844ed9fdbcdd512228f00565f2588ef4baa201da77b", + "images/blog/how-to-avoid-framework-fatigue-when-building-backends/cover.png": "1cbcf5ea25724a9f5554b66b02888e4b18168b3984e33c1fe644d2226f24f418", + "images/blog/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works/cover.png": "f378d12d6c5e5aa749a5699a625d0801c8b600f8c293e892ff0c68b1d4fe7f49", "images/blog/how-to-build-remote-tech-stack/1.png": "5c7a132f303345b4be898568c7ee194ea35df3a16a8636544c9367044ea7ba0d", "images/blog/how-to-build-remote-tech-stack/10.png": "3ecd41734ef650176ade1db64433c3d86da8a484c2791379f8ebf510573f691b", "images/blog/how-to-build-remote-tech-stack/2.png": "72d1cf92690007293bfe8d377e4315d17117fe53dcf3d0d90facfe18a4d32212", @@ -1023,6 +1025,7 @@ "images/blog/the-journey-and-meaning-behind-our-new-logo/lines.png": "99df0e374c0f9a29d3f964d71790741ed3b430af78dbc1bfff3f7a7096ff292d", "images/blog/the-journey-and-meaning-behind-our-new-logo/new_logo.png": "9831dd57d2f8d93d6cbdc1974444767e9bd5a7270229afb93da01a1597c4c87f", "images/blog/the-journey-and-meaning-behind-our-new-logo/old_logo.png": "0690abbd5e2720df68534729973ff0155c383900d64bcd297e1c67e517c785ce", + "images/blog/the-mental-model-every-developer-needs-for-backend-architecture/cover.png": "c45c6e41d02c64975dac8a6ce8e0e3b30c4ed7719128fce958659551418f9de5", "images/blog/the-shift-from-SaaS-to-Vertical-AI-what-startup-founders-need-to-know/cover-image.png": "e4030cb8b735baa8f4f6eec9d0d32233011759b160882015738cda2e79da14d6", "images/blog/the-subtle-art-of-hackathon ideation/cover.png": "a4007fb895ed8cb284e2409897282a784b803c199b91d58e90a2dd69f367ba33", "images/blog/threads-cover.png": "fa44d6cd70000ac7a62d3b9446b171f8e9fe1b27f157cb6ba2f98c1f8c043526", 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 0000000000..082ec792e5 --- /dev/null +++ b/src/routes/blog/post/how-to-avoid-framework-fatigue-when-building-backends/+page.markdoc @@ -0,0 +1,103 @@ +--- +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.png +timeToRead: 5 +author: aishwari +category: best-practices +featured: false +unlisted: true +--- +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. + +As covered in [backend mistakes that quietly cost small teams weeks](/blog/post/backend-mistakes-that-quietly-cost-small-teams-weeks), architecture decisions made early ripple across the entire product lifecycle. Framework churn is one of the most consistent sources of that kind of invisible drag. + +# 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](/blog/post/avoid-backend-overengineering) 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 0000000000..f1415d1c97 --- /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,107 @@ +--- +layout: post +title: How to build and ship a side project alone (The backend stack that works) +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.png +timeToRead: 5 +author: aishwari +category: startup +featured: false +unlisted: true +--- + +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 document-model 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. If you outgrow it or have specific requirements later, you can bring in an external database alongside Appwrite. There's no lock-in. + +For most projects, the built-in database is everything you need until you have a real scaling problem. At that point, you have the revenue to solve it properly. + +# 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 0000000000..975564f29b --- /dev/null +++ b/src/routes/blog/post/the-mental-model-every-developer-needs-for-backend-architecture/+page.markdoc @@ -0,0 +1,122 @@ +--- +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.png +timeToRead: 5 +author: aishwari +category: architecture +featured: false +unlisted: true +--- + +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. + +- **Relational or document 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/blog/how-to-avoid-framework-fatigue-when-building-backends/cover.png b/static/images/blog/how-to-avoid-framework-fatigue-when-building-backends/cover.png new file mode 100644 index 0000000000..9633ef1933 Binary files /dev/null and b/static/images/blog/how-to-avoid-framework-fatigue-when-building-backends/cover.png differ diff --git a/static/images/blog/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works/cover.png b/static/images/blog/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works/cover.png new file mode 100644 index 0000000000..173a305d28 Binary files /dev/null and b/static/images/blog/how-to-build-and-ship-a-side-project-alone-the-backend-stack-that-works/cover.png differ diff --git a/static/images/blog/the-mental-model-every-developer-needs-for-backend-architecture/cover.png b/static/images/blog/the-mental-model-every-developer-needs-for-backend-architecture/cover.png new file mode 100644 index 0000000000..2f0cbd8db9 Binary files /dev/null and b/static/images/blog/the-mental-model-every-developer-needs-for-backend-architecture/cover.png differ