[{"data":1,"prerenderedAt":157},["ShallowReactive",2],{"blog-understand-application-architecture":3},{"title":4,"description":7,"image":10,"category":11,"featured":12,"isPublished":12,"publishDate":13,"author":14,"links":15,"projects":16,"mainLanguage":17,"viewCount":18,"value":19,"content":20,"tableOfContents":23},{"en":5,"pl":6},"To understand software engineering","Zrozumieć architekturę aplikacji",{"en":8,"pl":9},"Learn the core concepts of web application architecture: frontend/backend split, monolith vs microservices, Docker, CI/CD pipelines, and VPS vs cloud hosting.","Poznaj kluczowe koncepcje architektury aplikacji: podział frontend/backend, monolit vs mikroserwisy, Docker, CI/CD oraz porównanie VPS i chmury.","https://files.jtuta.cloud/public/portfolio/blogs/JXhRtXCdUcjzOqcbp3EZWAodOUzbDp.png","devops",true,"2026-03-01T17:17:57.204Z",null,[],[],"pl",2,"understand-application-architecture",{"en":21,"pl":22},"\u003Ch2 id=\"application-architecture-the-foundation-of-every-project\" tabindex=\"-1\">Application architecture — the foundation of every project\u003C/h2>\n\u003Cp>\u003Cstrong>Application architecture\u003C/strong> is the way we divide and organize code, components, and system resources — so that the application is easy to develop, scale, and maintain. It's not just about how you write code, but also where it runs, how individual parts talk to each other, and how you deploy changes without disturbing users.\u003C/p>\n\u003Cp>Good architecture is invisible to the end user. Bad architecture is very visible — as slow pages, crashes during high traffic, and weekends spent debugging. This article will guide you through the most important concepts that every programmer should understand: from dividing the application into layers, through containerization and the cloud, to automatic deployments and scaling.\u003C/p>\n\u003Ch2 id=\"frontend-backend-and-separation-of-concerns\" tabindex=\"-1\">Frontend, backend, and separation of concerns\u003C/h2>\n\u003Cp>The first fundamental architectural decision you encounter in almost every web project is the \u003Cstrong>division into frontend and backend\u003C/strong>. It is worth understanding this well, because it affects everything — from team structure, through technologies, to the deployment method.\u003C/p>\n\u003Cp>\u003Cstrong>Frontend\u003C/strong> is the part of the application that the user sees. It runs in the browser or mobile app — it's HTML, CSS, and JavaScript, meaning everything responsible for appearance, animations, and interactions. Modern frontends are built in frameworks like React, Vue, or Angular, which allow creating complex interfaces as a set of components.\u003C/p>\n\u003Cp>\u003Cstrong>Backend\u003C/strong> is the &quot;brain&quot; of the application running on the server side. It handles business logic, communicates with the database, authenticates users, and processes data. The user never sees it directly but benefits from its effects with every action — clicking a button, logging in, or placing an order.\u003C/p>\n\u003Cp>Communication between them takes place via an \u003Cstrong>API\u003C/strong> \u003Cem>(Application Programming Interface)\u003C/em> — a set of clearly defined entry points through which the frontend can ask the backend for data or actions. The most popular pattern is \u003Cstrong>REST API\u003C/strong>, where each resource has its own URL, and operations on it correspond to HTTP methods: \u003Ccode>GET\u003C/code> for retrieving, \u003Ccode>POST\u003C/code> for creating, \u003Ccode>PUT\u003C/code>/\u003Ccode>PATCH\u003C/code> for updating, and \u003Ccode>DELETE\u003C/code> for deleting.\u003C/p>\n\u003Cp>This division has huge practical benefits. Frontend and backend can be developed independently and deployed separately. You can have multiple frontends (web, mobile, desktop) served by the same backend. You can also scale each part separately — if you have a lot of traffic on the site but few data operations, you can give more resources to the frontend without touching the backend.\u003C/p>\n\u003Ch3 id=\"bff-backend-for-frontend\" tabindex=\"-1\">BFF — Backend for Frontend\u003C/h3>\n\u003Cp>With more advanced systems, the \u003Cem>Backend for Frontend\u003C/em> pattern appears. Instead of one generic API, you create a separate backend for each client — one optimized for the web application, another for mobile. Each BFF can aggregate data from multiple services and return exactly what the given platform needs, without unnecessary data.\u003C/p>\n\u003Cp>This is an elegant solution to the problem that arises when you have one monolithic backend trying to serve 5 different clients with different needs. Instead of compromises in the API, each client gets &quot;their own&quot; backend.\u003C/p>\n\u003Ch2 id=\"monolith-vs-microservices-the-great-architecture-dilemma\" tabindex=\"-1\">Monolith vs. microservices — the great architecture dilemma\u003C/h2>\n\u003Cp>This is one of the hottest questions in software engineering and there is no simple answer. But there is a reasonable answer, which I will try to present here.\u003C/p>\n\u003Ch3 id=\"monolith-simple-strength\" tabindex=\"-1\">Monolith — simple strength\u003C/h3>\n\u003Cp>A \u003Cstrong>Monolith\u003C/strong> is an application where all the code — authentication, business logic, payment processing, notifications — is deployed together as a single process. This is probably how you started building your first application, and there is nothing wrong with that.\u003C/p>\n\u003Cp>The monolith has real advantages: it is simpler to debug, easier to run locally, and does not require managing complex network infrastructure between components. For a small team and an application in the early phase, a monolith is often the \u003Cem>right\u003C/em> decision. Large companies like Stack Overflow and Shopify handled enormous traffic on monolithic architecture for many years.\u003C/p>\n\u003Cp>Problems begin when the application grows. One module can cause the entire system to crash. It is harder to scale just one component — if the payment processing module needs more resources, you must scale the entire application. Large codebases become difficult to understand, and onboarding new developers takes weeks.\u003C/p>\n\u003Ch3 id=\"microservices-divided-strength\" tabindex=\"-1\">Microservices — divided strength\u003C/h3>\n\u003Cp>\u003Cstrong>Microservices\u003C/strong> is an approach where you divide the application into small, independent services — each is responsible for a specific fragment of the business domain and communicates with others via API or message queues. User service, order service, payment service, notification service — each lives its own life.\u003C/p>\n\u003Cp>The advantages are real and important at scale. Each service can be:\u003C/p>\n\u003Cul>\n\u003Cli>deployed independently without risking the crash of the entire application\u003C/li>\n\u003Cli>written in a different technology appropriate for the task\u003C/li>\n\u003Cli>scaled separately — you can give 20 instances to the payment service and 2 instances to the reporting service\u003C/li>\n\u003Cli>developed by a separate, small team that understands the entirety of their service\u003C/li>\n\u003C/ul>\n\u003Cp>Failure of one service does not have to mean failure of the system — you can handle degradation gracefully, e.g., turn off product recommendations when the recommendation service is down, but allow orders to be placed.\u003C/p>\n\u003Ch3 id=\"when-monolith-when-microservices\" tabindex=\"-1\">When monolith, when microservices?\u003C/h3>\n\u003Cp>Microservices sound beautiful, but they have serious entry costs. You need mature infrastructure: service discovery, load balancing, distributed tracing, centralized logging, secret management. Debugging a problem that passes through 5 services is a completely different challenge than debugging a monolith. And every call between services is network latency and a potential point of failure.\u003C/p>\n\u003Cp>The pragmatic answer: \u003Cstrong>start with a monolith, move to microservices when you have a specific reason\u003C/strong>. When one module requires 10x more scaling than the rest, when different teams constantly get in each other's way during deployments, when one component requires a different technology — these are real signals to split. Do not do it in advance &quot;because that's how big companies do it&quot;. Amazon, Netflix, Uber split their monoliths when they had already encountered concrete scaling problems — not immediately.\u003C/p>\n\u003Cp>A compromise solution is also a \u003Cstrong>modular monolith architecture\u003C/strong> — one deployment, but code divided into distinct, loosely coupled modules with clear boundaries. This facilitates later splitting into services when needed.\u003C/p>\n\u003Ch2 id=\"containerization-docker-and-the-revolution-in-environments\" tabindex=\"-1\">Containerization — Docker and the revolution in environments\u003C/h2>\n\u003Cp>The classic developer problem sounds like: \u003Cem>&quot;it works on my machine&quot;\u003C/em>. The code works on the developer's laptop but crashes on the production server. The reasons are differences in library versions, environment variables, the operating system. \u003Cstrong>Containers\u003C/strong> solve this problem once and for all.\u003C/p>\n\u003Cp>\u003Cstrong>Docker\u003C/strong> is the most popular containerization technology. A container is an isolated package containing the application and all its dependencies — code, runtime, libraries, environment variables, configuration files. A container runs identically regardless of where you run it: on a laptop, on a CI server, on production.\u003C/p>\n\u003Cp>A container is not the same as a virtual machine. A VM emulates an entire computer with its own operating system — it is heavy and slow to start. A container shares the host kernel and isolates only processes — it is lightweight, starts in seconds, and takes up tens of MB instead of gigabytes.\u003C/p>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:light-dark(#fff, #24292e);--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;color:light-dark(#24292e, #e1e4e8);--shiki-light:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Przykład Dockerfile dla aplikacji Node.js\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">FROM\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> node:20-alpine\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Ustawiamy katalog roboczy\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">WORKDIR\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> /app\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Kopiujemy pliki zależności i instalujemy je (osobna warstwa = szybszy build)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">COPY\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> package*.json ./\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">RUN\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> npm ci --only=production\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Kopiujemy kod aplikacji\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">COPY\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> . .\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Budujemy aplikację\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">RUN\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> npm run build\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Expose port 3000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">EXPOSE\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> 3000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Uruchamiamy aplikację\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">CMD\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> [\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"node\"\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"dist/server.js\"\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>\u003Cstrong>Docker Compose\u003C/strong> allows defining and running multi-container applications. Instead of manually running the database, redis, backend, and frontend in the local environment — you write one \u003Ccode>docker-compose.yml\u003C/code> file and run everything with a single command.\u003C/p>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:light-dark(#fff, #24292e);--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;color:light-dark(#24292e, #e1e4e8);--shiki-light:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># docker-compose.yml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">services\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  api\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    build\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">./backend\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    ports\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"3000:3000\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    environment\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">DATABASE_URL=postgres://user:pass@db:5432/myapp\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">REDIS_URL=redis://cache:6379\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    depends_on\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">db\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">cache\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  db\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    image\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">postgres:16-alpine\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    environment\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">POSTGRES_USER=user\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">POSTGRES_PASSWORD=pass\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">POSTGRES_DB=myapp\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    volumes\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">postgres_data:/var/lib/postgresql/data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  cache\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    image\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">redis:7-alpine\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">volumes\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  postgres_data\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Starting the entire development environment: \u003Ccode>docker-compose up\u003C/code>. A new developer joins the project — clones the repo, runs one command, and has a working environment in a few minutes, without installing anything manually.\u003C/p>\n\u003Ch3 id=\"kubernetes-orchestration-for-real\" tabindex=\"-1\">Kubernetes — orchestration for real\u003C/h3>\n\u003Cp>When you have tens of containers to manage across multiple servers, Docker Compose is no longer enough. Here enters \u003Cstrong>Kubernetes\u003C/strong> (in short: K8s).\u003C/p>\n\u003Cp>Kubernetes is a container orchestration platform — it automatically places containers on servers, restarts those that fail, scales the number of instances depending on traffic, manages zero-downtime updates, and much more. It is the de facto standard in large production environments.\u003C/p>\n\u003Cp>Key concepts in Kubernetes are \u003Cstrong>Pod\u003C/strong> (the smallest unit — one or several containers), \u003Cstrong>Deployment\u003C/strong> (declarative definition of how many pods should run and what they should look like), \u003Cstrong>Service\u003C/strong> (a stable entry point to a set of pods — even when pods are restarted and get new IPs, the Service remains constant), and \u003Cstrong>Ingress\u003C/strong> (managing HTTP traffic from outside to services inside the cluster).\u003C/p>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:light-dark(#fff, #24292e);--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;color:light-dark(#24292e, #e1e4e8);--shiki-light:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Przykład: Deployment w Kubernetes\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">apiVersion\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">apps/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">kind\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Deployment\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">metadata\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">api-deployment\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">spec\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  replicas\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#005CC5, #79B8FF);--shiki-light:#005CC5;--shiki-dark:#79B8FF\">3\u003C/span>\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # Chcemy 3 instancje\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  selector\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    matchLabels\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">      app\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">api\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  template\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    metadata\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">      labels\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        app\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">api\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    spec\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">      containers\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">api\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        image\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">myregistry/api:v1.2.3\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        ports\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">        - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">containerPort\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#005CC5, #79B8FF);--shiki-light:#005CC5;--shiki-dark:#79B8FF\">3000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        resources\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">          requests\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">            memory\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"128Mi\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">            cpu\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"100m\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">          limits\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">            memory\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"512Mi\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">            cpu\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"500m\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Kubernetes is powerful, but has a high learning curve and significant operational complexity. For small projects, it is definitely overkill — Docker Compose or managed platforms like Railway, Render, or \u003Ca href=\"http://Fly.io\" target=\"_blank\" rel=\"noopener noreferrer\">Fly.io\u003C/a> will be a much better choice.\u003C/p>\n\u003Ch2 id=\"cloud-vs-vps-where-to-run-the-application\" tabindex=\"-1\">Cloud vs. VPS — where to run the application?\u003C/h2>\n\u003Cp>When your application is ready for deployment, you face the question: where to run it? The market offers two main approaches: \u003Cstrong>public cloud\u003C/strong> and \u003Cstrong>private VPS servers\u003C/strong>.\u003C/p>\n\u003Ch3 id=\"cloud-solutions\" tabindex=\"-1\">Cloud solutions\u003C/h3>\n\u003Cp>\u003Cstrong>Public cloud\u003C/strong> is infrastructure provided by large companies — Amazon Web Services (AWS), Google Cloud Platform (GCP), and Microsoft Azure are the three dominating the market. Besides them, there are many higher-level platforms like Vercel, Netlify, Railway, or \u003Ca href=\"http://Fly.io\" target=\"_blank\" rel=\"noopener noreferrer\">Fly.io\u003C/a>, which abstract away a large part of the complexity.\u003C/p>\n\u003Cp>The cloud offers several unique capabilities. \u003Cstrong>On-demand scaling\u003C/strong> — you can increase resources in minutes when 10x more traffic suddenly appears, and decrease them when traffic drops, paying only for what you use. \u003Cstrong>Managed services\u003C/strong> — instead of manually configuring and maintaining a database, cache, message queues, or CDN, you can use ready-made, managed services: Amazon RDS, ElastiCache, SQS. You don't worry about security patches, backups, failover — the provider does it for you. \u003Cstrong>Global infrastructure\u003C/strong> — you can run the application in regions all over the world, minimizing latency for users from different continents.\u003C/p>\n\u003Cp>The main disadvantage of the cloud is \u003Cstrong>cost\u003C/strong>. With ill-considered use, bills can be surprisingly high, especially in AWS, where the payment model is very granular. The second problem is \u003Cstrong>vendor lock-in\u003C/strong> — when you start deeply using specific AWS services (Lambda, DynamoDB, SQS), migration to another provider becomes expensive.\u003C/p>\n\u003Ch3 id=\"vps-the-classic-alternative\" tabindex=\"-1\">VPS — the classic alternative\u003C/h3>\n\u003Cp>\u003Cstrong>VPS\u003C/strong> \u003Cem>(Virtual Private Server)\u003C/em> is a virtual machine on a physical server that you rent from a provider — DigitalOcean, Hetzner, Linode/Akamai, OVH. You get a server with a specific amount of CPU, RAM, and disk, you pay a fixed monthly rate, and you do whatever you want on it.\u003C/p>\n\u003Cp>VPS is cheaper for predictable loads — for $20-50 a month you can have a solid server for an application serving thousands of users daily. You have full control over the environment and know exactly how much you will pay at the end of the month.\u003C/p>\n\u003Cp>The disadvantage is that \u003Cstrong>all infrastructure management lies on your side\u003C/strong>. System updates, firewall configuration, SSL certificates, backups, monitoring — all of this is your responsibility. There is no built-in scaling — if you need more resources, you must manually change the server plan or add new machines and configure a load balancer.\u003C/p>\n\u003Ch3 id=\"how-to-choose\" tabindex=\"-1\">How to choose?\u003C/h3>\n\u003Cp>Practical heuristics: if you are just starting or have a small project with predictable traffic, \u003Cstrong>VPS from Hetzner is probably the best choice\u003C/strong> — the price-to-performance ratio is outstanding, and the simplicity of management is sufficient. When the application grows, traffic becomes unpredictable, or you need advanced managed services, it is worth considering the cloud. Many companies use a hybrid: database on managed RDS in AWS, application on cheaper VPSs from Hetzner.\u003C/p>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Aspect\u003C/th>\n\u003Cth>VPS (e.g., Hetzner)\u003C/th>\n\u003Cth>Cloud (e.g., AWS)\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>Cost (constant traffic)\u003C/td>\n\u003Ctd>Low, predictable\u003C/td>\n\u003Ctd>Higher, can be surprising\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Cost (spiky traffic)\u003C/td>\n\u003Ctd>Need to overprovision\u003C/td>\n\u003Ctd>Pay only for usage\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Management\u003C/td>\n\u003Ctd>Manual, full control\u003C/td>\n\u003Ctd>Managed services available\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Scaling\u003C/td>\n\u003Ctd>Manual / limited\u003C/td>\n\u003Ctd>Automatic, elastic\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Learning curve\u003C/td>\n\u003Ctd>Low\u003C/td>\n\u003Ctd>High for advanced services\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\n\u003Ch2 id=\"deployment-and-cicd-how-to-deploy-applications-without-pain\" tabindex=\"-1\">Deployment and CI/CD — how to deploy applications without pain\u003C/h2>\n\u003Cp>\u003Cstrong>Deployment\u003C/strong> is the process of deploying a new version of the application to the production server. Done manually — by copying files via FTP, manually running commands on the server — it is slow, prone to errors, and stressful. The modern approach is the automation of this process through \u003Cstrong>CI/CD\u003C/strong>.\u003C/p>\n\u003Ch3 id=\"cicd-what-does-it-actually-mean\" tabindex=\"-1\">CI/CD — what does it actually mean?\u003C/h3>\n\u003Cp>\u003Cstrong>CI\u003C/strong> \u003Cem>(Continuous Integration)\u003C/em> is the practice of frequently merging code changes to the main repository branch, automatically running tests in the process. The goal is early problem detection — instead of integrating changes from multiple developers once a week and discovering conflicts, you do it multiple times a day.\u003C/p>\n\u003Cp>\u003Cstrong>CD\u003C/strong> can mean two things: \u003Cem>Continuous Delivery\u003C/em> — every change is automatically prepared for deployment, but deployment requires manual confirmation, or \u003Cem>Continuous Deployment\u003C/em> — every change goes through the pipeline and lands automatically on production without human intervention.\u003C/p>\n\u003Cp>A popular CI/CD platform is \u003Cstrong>GitHub Actions\u003C/strong>, but there are also GitLab CI, CircleCI, Jenkins, and many others. Here is how a simple pipeline might look:\u003C/p>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:light-dark(#fff, #24292e);--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;color:light-dark(#24292e, #e1e4e8);--shiki-light:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># .github/workflows/deploy.yml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Deploy to Production\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#005CC5, #79B8FF);--shiki-light:#005CC5;--shiki-dark:#79B8FF\">on\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  push\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    branches\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: [\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">main\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">jobs\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  test\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    runs-on\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">ubuntu-latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    steps\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">uses\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">actions/checkout@v4\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Setup Node.js\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        uses\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">actions/setup-node@v4\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        with\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">          node-version\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'20'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">          \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Install dependencies\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">npm ci\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">        \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Run tests\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">npm test\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">        \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Run linter\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">npm run lint\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  deploy\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    needs\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">test\u003C/span>\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # Deploy tylko jeśli testy przeszły\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    runs-on\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">ubuntu-latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    steps\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">uses\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">actions/checkout@v4\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Build Docker image\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">docker build -t myapp:${{ github.sha }} .\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">        \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Push to registry\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">|\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">          docker tag myapp:${{ github.sha }} registry.io/myapp:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">          docker push registry.io/myapp:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">          \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Deploy to server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">|\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">          ssh user@myserver.com \"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">            docker pull registry.io/myapp:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">            docker-compose -f /app/docker-compose.prod.yml up -d\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">          \"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Now every time we push code to the \u003Ccode>main\u003C/code> branch, GitHub automatically runs tests and if they pass — deploys the new version. Zero manual work.\u003C/p>\n\u003Ch3 id=\"deployment-strategies-zero-downtime\" tabindex=\"-1\">Deployment strategies — zero downtime\u003C/h3>\n\u003Cp>Naive deployment looks like this: you stop the old version, start the new one. During this time, the application is unavailable. For serious services, this is unacceptable.\u003C/p>\n\u003Cp>\u003Cstrong>Rolling deployment\u003C/strong> consists of gradually replacing instances of the old version with new ones. At any given moment, some servers handle the old version, some the new one, and traffic is distributed by a load balancer. Users do not experience downtime.\u003C/p>\n\u003Cp>\u003Cstrong>Blue-green deployment\u003C/strong> is maintaining two identical environments — &quot;blue&quot; (current production) and &quot;green&quot; (new version). You deploy to green, test, and then with one switch in the load balancer, move all traffic from blue to green. Rollback in case of problems is another single switch — immediate.\u003C/p>\n\u003Cp>\u003Cstrong>Canary deployment\u003C/strong> is carefully releasing a new version to a small percentage of users — say 5%. You monitor errors and metrics. If everything is okay, you gradually increase the percentage. If a problem appears, you revert the change affecting only 5% of users.\u003C/p>\n\u003Ch2 id=\"scaling-optimization-and-production-environment\" tabindex=\"-1\">Scaling, optimization, and production environment\u003C/h2>\n\u003Ch3 id=\"scaling-horizontal-vs-vertical\" tabindex=\"-1\">Scaling — horizontal vs. vertical\u003C/h3>\n\u003Cp>When the application cannot keep up with growing traffic, you have two approaches to scaling.\u003C/p>\n\u003Cp>\u003Cstrong>Vertical scaling\u003C/strong> \u003Cem>(vertical scaling / scale up)\u003C/em> means giving the server more resources — more RAM, faster CPU, more disks. It is simple and does not require code changes, but has a hard limit — eventually, you cannot add infinitely many resources to one machine, and it is also quite expensive.\u003C/p>\n\u003Cp>\u003Cstrong>Horizontal scaling\u003C/strong> \u003Cem>(horizontal scaling / scale out)\u003C/em> is running multiple instances of the application and distributing traffic between them via a \u003Cstrong>load balancer\u003C/strong>. It is more complex — the application must be stateless (not storing user sessions locally on the server) or use an external state store like Redis — but it gives practically unlimited scalability.\u003C/p>\n\u003Cp>Modern applications are designed with horizontal scaling in mind. The principle is: \u003Cem>treat servers like cattle, not pets\u003C/em> — treat servers like cattle, not like pets. Each server is replaceable, can fail, and be replaced by a new one automatically.\u003C/p>\n\u003Ch3 id=\"development-vs-production-environment\" tabindex=\"-1\">Development vs. production environment\u003C/h3>\n\u003Cp>Differences between the local and production environments are one of the most common sources of problems. It is important to understand them and manage them consciously.\u003C/p>\n\u003Cp>In the \u003Cstrong>development environment\u003C/strong>, the priority is iteration speed: hot reloading (changes in code visible immediately), verbose logging (detailed error logs), disabled cache and optimizations (to see current data), local database with test data, environment variables pointing to local services.\u003C/p>\n\u003Cp>In the \u003Cstrong>production environment\u003C/strong>, priorities are completely different: minimized and optimized code (tree shaking, minification, compression), aggressive cache (CDN for static resources, cache at the database level), only necessary logs (logging every request at high traffic kills performance), environmental secrets managed by vault or secrets manager, monitoring and alerts.\u003C/p>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:light-dark(#fff, #24292e);--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;color:light-dark(#24292e, #e1e4e8);--shiki-light:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># .env.development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">NODE_ENV\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">LOG_LEVEL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">debug\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">DATABASE_URL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">postgres://localhost:5432/myapp_dev\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">CACHE_TTL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">0\u003C/span>\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # Wyłączone cache w devie\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># .env.production\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">NODE_ENV\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">production\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">LOG_LEVEL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">warn\u003C/span>\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # Tylko ostrzeżenia i błędy\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">DATABASE_URL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">postgres://prod-db.internal:5432/myapp\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">CACHE_TTL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">3600\u003C/span>\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # Cache na godzinę\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>It is also key to separate configuration from code. \u003Cstrong>Never\u003C/strong> keep passwords, API keys, connection strings in the Git repository. Use environment variables, dedicated secret managers (HashiCorp Vault, AWS Secrets Manager), or platforms that manage this for you (Vercel, Railway, Heroku have built-in secrets support).\u003C/p>\n\u003Ch3 id=\"monitoring-and-observability\" tabindex=\"-1\">Monitoring and observability\u003C/h3>\n\u003Cp>A production application that you do not monitor is an application whose problems you do not know. \u003Cstrong>Observability\u003C/strong> \u003Cem>(observability)\u003C/em> is the ability to understand the internal state of a system based on its external outputs. It consists of three pillars:\u003C/p>\n\u003Cp>\u003Cstrong>Logs\u003C/strong> are a sequential record of events in the system. In production, use structured logs in JSON format, aggregate them in one place (Datadog, Grafana Loki, CloudWatch), and define alerts for critical errors. A good log contains a timestamp, level (INFO/WARN/ERROR), message, request ID (allows tracking a single request across multiple services), and context.\u003C/p>\n\u003Cp>\u003Cstrong>Metrics\u003C/strong> are numbers measured over time: number of requests per second, response time (p95, p99), CPU and RAM usage, queue size. Prometheus with Grafana is a popular, open-source stack for collecting and visualizing metrics.\u003C/p>\n\u003Cp>\u003Cstrong>Tracing\u003C/strong> is tracking a single request through all system components — essential in microservices architecture. When a request passes through 6 services, distributed tracing allows you to see where the bottleneck is and where errors appear.\u003C/p>\n\u003Ch2 id=\"summary-architecture-is-a-long-game\" tabindex=\"-1\">Summary — architecture is a long game\u003C/h2>\n\u003Cp>Application architecture is not a one-time decision — it is a set of choices that evolve along with the product. No solution is perfect for every context and every scale.\u003C/p>\n\u003Cp>If I had to draw a few most important conclusions from this article, they would sound like this. \u003Cstrong>Start simply\u003C/strong> — a monolith, one VPS, manual deployment is better than an overcomplicated microservices architecture that is difficult to maintain and debug with a 3-person team. \u003Cstrong>Containerize from the beginning\u003C/strong> — Docker eliminates the classic &quot;it works on my machine&quot; problem and facilitates a later transition to more complex infrastructure. \u003Cstrong>Automate deployment\u003C/strong> — CI/CD is not a luxury but a necessity; every minute spent on manual deployments is a waste of time and a source of errors. \u003Cstrong>Separate configuration from code\u003C/strong> — secrets in the repository are a time bomb. \u003Cstrong>Monitor production\u003C/strong> — an application without monitoring is an application whose problems you learn about from users.\u003C/p>\n\u003Cp>Architecture is the foundation. You don't see it when it's good — but you really see it when it's bad. It is worth investing time in thinking it through, even if at first it seems to slow down development. In the long run, good architecture allows you to develop the product faster, more confidently, and with less stress.\u003C/p>\n","\u003Ch2 id=\"architektura-aplikacji-fundament-kazdego-projektu\" tabindex=\"-1\">Architektura aplikacji — fundament każdego projektu\u003C/h2>\n\u003Cp>\u003Cstrong>Architektura aplikacji\u003C/strong> to sposób, w jaki dzielimy i organizujemy kod, komponenty i zasoby systemu — tak, żeby aplikacja była łatwa w rozwijaniu, skalowaniu i utrzymaniu. To nie tylko to, jak piszesz kod, ale też gdzie on działa, jak poszczególne części ze sobą rozmawiają i jak wdrażasz zmiany bez przeszkadzania użytkownikom.\u003C/p>\n\u003Cp>Dobra architektura jest niewidoczna dla końcowego użytkownika. Zła architektura jest bardzo widoczna — jako wolne strony, awarie podczas wzmożonego ruchu i spędzone na debugowaniu weekendy. Ten artykuł przeprowadzi Cię przez najważniejsze koncepcje, które każdy programista powinien rozumieć: od podziału aplikacji na warstwy, przez konteneryzację i chmurę, aż po automatyczne wdrożenia i skalowanie.\u003C/p>\n\u003Ch2 id=\"frontend-backend-i-podzia-obowiazkow\" tabindex=\"-1\">Frontend, backend i podział obowiązków\u003C/h2>\n\u003Cp>Pierwsza fundamentalna decyzja architektoniczna, z którą spotykasz się w niemal każdym projekcie webowym, to \u003Cstrong>podział na frontend i backend\u003C/strong>. Warto to zrozumieć dobrze, bo wpływa na wszystko — od struktury zespołu, przez technologie, aż po sposób deploymentu.\u003C/p>\n\u003Cp>\u003Cstrong>Frontend\u003C/strong> to ta część aplikacji, którą widzi użytkownik. Działa w przeglądarce lub w aplikacji mobilnej — to HTML, CSS i JavaScript, czyli wszystko co odpowiada za wygląd, animacje i interakcje. Nowoczesne frontendy buduje się w frameworkach takich jak React, Vue czy Angular, które pozwalają tworzyć złożone interfejsy jako zbiór komponentów.\u003C/p>\n\u003Cp>\u003Cstrong>Backend\u003C/strong> to &quot;mózg&quot; aplikacji działający po stronie serwera. Obsługuje logikę biznesową, komunikuje się z bazą danych, autentykuje użytkowników i przetwarza dane. Użytkownik nigdy go bezpośrednio nie widzi, ale korzysta z jego efektów przy każdej akcji — kliknięciu przycisku, zalogowaniu czy złożeniu zamówienia.\u003C/p>\n\u003Cp>Komunikacja między nimi odbywa się przez \u003Cstrong>API\u003C/strong> \u003Cem>(Application Programming Interface)\u003C/em> — zestaw jasno zdefiniowanych punktów wejścia, przez które frontend może prosić backend o dane lub akcje. Najpopularniejszym wzorcem jest \u003Cstrong>REST API\u003C/strong>, gdzie każdy zasób ma swój URL, a operacje na nim odpowiadają metodom HTTP: \u003Ccode>GET\u003C/code> dla pobierania, \u003Ccode>POST\u003C/code> dla tworzenia, \u003Ccode>PUT\u003C/code>/\u003Ccode>PATCH\u003C/code> dla aktualizacji i \u003Ccode>DELETE\u003C/code> dla usuwania.\u003C/p>\n\u003Cp>Ten podział ma ogromne praktyczne korzyści. Frontend i backend można rozwijać niezależnie i wdrażać osobno. Można mieć kilka frontendów (web, mobile, desktop) obsługiwanych przez ten sam backend. Można też skalować każdą część oddzielnie — jeśli masz dużo ruchu na stronie, ale mało operacji na danych, możesz dać więcej zasobów frontendowi bez ruszania backendu.\u003C/p>\n\u003Ch3 id=\"bff-backend-for-frontend\" tabindex=\"-1\">BFF — Backend for Frontend\u003C/h3>\n\u003Cp>Przy bardziej zaawansowanych systemach pojawia się wzorzec \u003Cem>Backend for Frontend\u003C/em>. Zamiast jednego generycznego API, tworzysz osobny backend dla każdego klienta — jeden zoptymalizowany pod aplikację webową, drugi pod mobilną. Każdy BFF może agregować dane z wielu serwisów i zwracać dokładnie to, czego dana platforma potrzebuje, bez zbędnych danych.\u003C/p>\n\u003Cp>To eleganckie rozwiązanie problemu, który pojawia się gdy masz jeden monolityczny backend próbujący obsłużyć 5 różnych klientów z różnymi potrzebami. Zamiast kompromisów w API, każdy klient dostaje &quot;swój&quot; backend.\u003C/p>\n\u003Ch2 id=\"monolit-vs-mikroserwisy-wielki-dylemat-architektury\" tabindex=\"-1\">Monolit vs. mikroserwisy — wielki dylemat architektury\u003C/h2>\n\u003Cp>To jedno z najgorętszych pytań w inżynierii oprogramowania i nie ma na nie prostej odpowiedzi. Ale jest odpowiedź rozsądna, którą postaram się tu przedstawić.\u003C/p>\n\u003Ch3 id=\"monolit-prosta-sia\" tabindex=\"-1\">Monolit — prosta siła\u003C/h3>\n\u003Cp>\u003Cstrong>Monolit\u003C/strong> to aplikacja, w której cały kod — autentykacja, logika biznesowa, obsługa płatności, powiadomienia — jest wdrożony razem jako jeden proces. To prawdopodobnie sposób, w jaki zacząłeś budować swoją pierwszą aplikację, i nie ma w tym nic złego.\u003C/p>\n\u003Cp>Monolit ma realne zalety: jest prostszy do debugowania, łatwiejszy do lokalnego uruchomienia i nie wymaga zarządzania złożoną infrastrukturą sieciową między komponentami. Dla małego zespołu i aplikacji w początkowej fazie monolit często jest \u003Cem>właściwą\u003C/em> decyzją. Duże firmy jak Stack Overflow i Shopify przez wiele lat obsługiwały ogromny ruch na architekturze monolitycznej.\u003C/p>\n\u003Cp>Problemy zaczynają się gdy aplikacja rośnie. Jeden moduł może powodować awarie całego systemu. Trudniej skalować tylko jeden komponent — jeśli moduł obsługi płatności potrzebuje więcej zasobów, musisz skalować całą aplikację. Duże bazy kodu stają się trudne do zrozumienia, a onboarding nowych developerów trwa tygodniami.\u003C/p>\n\u003Ch3 id=\"mikroserwisy-podzielona-sia\" tabindex=\"-1\">Mikroserwisy — podzielona siła\u003C/h3>\n\u003Cp>\u003Cstrong>Mikroserwisy\u003C/strong> to podejście, w którym aplikację dzielisz na małe, niezależne serwisy — każdy odpowiada za konkretny fragment domeny biznesowej i komunikuje się z innymi przez API lub kolejki wiadomości. Serwis użytkowników, serwis zamówień, serwis płatności, serwis powiadomień — każdy żyje własnym życiem.\u003C/p>\n\u003Cp>Zalety są realne i ważne w skali. Każdy serwis można:\u003C/p>\n\u003Cul>\n\u003Cli>wdrożyć niezależnie bez ryzykowania awarii całej aplikacji\u003C/li>\n\u003Cli>pisać w innej technologii odpowiedniej do zadania\u003C/li>\n\u003Cli>skalować osobno — możesz dać 20 instancji serwisowi płatności i 2 instancje serwisowi raportów\u003C/li>\n\u003Cli>rozwijać przez oddzielny, mały zespół, który rozumie całość swojego serwisu\u003C/li>\n\u003C/ul>\n\u003Cp>Awaria jednego serwisu nie musi oznaczać awarii systemu — możesz obsłużyć degradację gracefully, np. wyłączyć rekomendacje produktów gdy serwis rekomendacji pada, ale pozwolić na składanie zamówień.\u003C/p>\n\u003Ch3 id=\"kiedy-monolit-kiedy-mikroserwisy\" tabindex=\"-1\">Kiedy monolit, kiedy mikroserwisy?\u003C/h3>\n\u003Cp>Mikroserwisy brzmią pięknie, ale mają poważne koszty wejścia. Potrzebujesz dojrzałej infrastruktury: service discovery, load balancing, distributed tracing, centralne logowanie, zarządzanie sekrekami. Debugging problemu, który przechodzi przez 5 serwisów, to zupełnie inne wyzwanie niż debugowanie monolitu. I każde wywołanie między serwisami to sieciowe opóźnienie i potencjalny punkt awarii.\u003C/p>\n\u003Cp>Pragmatyczna odpowiedź: \u003Cstrong>zacznij od monolitu, przejdź do mikroserwisów gdy masz konkretny powód\u003C/strong>. Gdy jeden moduł wymaga 10x więcej skalowania niż reszta, gdy różne zespoły ciągle wchodzą sobie w drogę przy deploymentach, gdy jeden komponent wymaga innej technologii — to są prawdziwe sygnały do podziału. Nie rób tego z góry &quot;bo tak się robi w dużych firmach&quot;. Amazon, Netflix, Uber podzielili swoje monolity, gdy już napotkali konkretne problemy skali — nie od razu.\u003C/p>\n\u003Cp>Kompromisowym rozwiązaniem jest też \u003Cstrong>modularna architektura monolitu\u003C/strong> — jeden deployment, ale kod podzielony na wyraźne, luźno powiązane moduły z wyraźnymi granicami. To ułatwia późniejszy podział na serwisy gdy będzie potrzebny.\u003C/p>\n\u003Ch2 id=\"konteneryzacja-docker-i-rewolucja-w-srodowiskach\" tabindex=\"-1\">Konteneryzacja — Docker i rewolucja w środowiskach\u003C/h2>\n\u003Cp>Klasyczny problem developerski brzmi: \u003Cem>&quot;u mnie działa&quot;\u003C/em>. Kod działa na laptopie developera, ale wysypuje się na serwerze produkcyjnym. Powodem są różnice w wersjach bibliotek, zmiennych środowiskowych, systemie operacyjnym. \u003Cstrong>Kontenery\u003C/strong> rozwiązują ten problem raz na zawsze.\u003C/p>\n\u003Cp>\u003Cstrong>Docker\u003C/strong> to najpopularniejsza technologia konteneryzacji. Kontener to izolowany pakiet zawierający aplikację i wszystkie jej zależności — kod, runtime, biblioteki, zmienne środowiskowe, pliki konfiguracyjne. Kontener działa identycznie niezależnie od tego, gdzie go uruchomisz: na laptopie, na serwerze CI, na produkcji.\u003C/p>\n\u003Cp>Kontener to nie to samo co maszyna wirtualna. VM emuluje cały komputer z własnym systemem operacyjnym — jest ciężka i wolna w starcie. Kontener współdzieli kernel hosta i izoluje tylko procesy — jest lekki, startuje w sekundy i zajmuje dziesiątki MB zamiast gigabajtów.\u003C/p>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:light-dark(#fff, #24292e);--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;color:light-dark(#24292e, #e1e4e8);--shiki-light:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Przykład Dockerfile dla aplikacji Node.js\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">FROM\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> node:20-alpine\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Ustawiamy katalog roboczy\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">WORKDIR\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> /app\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Kopiujemy pliki zależności i instalujemy je (osobna warstwa = szybszy build)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">COPY\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> package*.json ./\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">RUN\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> npm ci --only=production\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Kopiujemy kod aplikacji\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">COPY\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> . .\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Budujemy aplikację\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">RUN\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> npm run build\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Expose port 3000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">EXPOSE\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> 3000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Uruchamiamy aplikację\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">CMD\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> [\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"node\"\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"dist/server.js\"\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>\u003Cstrong>Docker Compose\u003C/strong> pozwala definiować i uruchamiać wielokontenerowe aplikacje. Zamiast ręcznie uruchamiać bazę danych, redis, backend i frontend na lokalnym środowisku — piszesz jeden plik \u003Ccode>docker-compose.yml\u003C/code> i uruchamiasz wszystko jedną komendą.\u003C/p>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:light-dark(#fff, #24292e);--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;color:light-dark(#24292e, #e1e4e8);--shiki-light:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># docker-compose.yml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">services\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  api\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    build\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">./backend\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    ports\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"3000:3000\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    environment\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">DATABASE_URL=postgres://user:pass@db:5432/myapp\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">REDIS_URL=redis://cache:6379\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    depends_on\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">db\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">cache\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  db\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    image\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">postgres:16-alpine\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    environment\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">POSTGRES_USER=user\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">POSTGRES_PASSWORD=pass\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">POSTGRES_DB=myapp\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    volumes\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">postgres_data:/var/lib/postgresql/data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  cache\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    image\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">redis:7-alpine\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">volumes\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  postgres_data\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Uruchomienie całego środowiska developerskiego: \u003Ccode>docker-compose up\u003C/code>. Nowy developer dołącza do projektu — klonuje repo, uruchamia jedną komendę i ma działające środowisko za kilka minut, bez instalowania czegokolwiek ręcznie.\u003C/p>\n\u003Ch3 id=\"kubernetes-orkiestracja-na-powaznie\" tabindex=\"-1\">Kubernetes — orkiestracja na poważnie\u003C/h3>\n\u003Cp>Gdy masz dziesiątki kontenerów do zarządzania na wielu serwerach, Docker Compose przestaje wystarczyć. Tu wchodzi \u003Cstrong>Kubernetes\u003C/strong> (w skrócie: K8s).\u003C/p>\n\u003Cp>Kubernetes to platforma do orkiestracji kontenerów — automatycznie rozmieszcza kontenery na serwerach, restartuje te które padną, skaluje ilość instancji w zależności od ruchu, zarządza aktualizacjami bez przestojów i wiele więcej. To de facto standard w dużych środowiskach produkcyjnych.\u003C/p>\n\u003Cp>Kluczowe koncepcje w Kubernetes to \u003Cstrong>Pod\u003C/strong> (najmniejsza jednostka — jeden lub kilka kontenerów), \u003Cstrong>Deployment\u003C/strong> (deklaratywna definicja jak wiele podów ma działać i jak powinny wyglądać), \u003Cstrong>Service\u003C/strong> (stabilny punkt wejścia do zestawu podów — nawet gdy pody są restartowane i dostają nowe IP, Service pozostaje stały) i \u003Cstrong>Ingress\u003C/strong> (zarządzanie ruchem HTTP z zewnątrz do serwisów wewnątrz klastra).\u003C/p>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:light-dark(#fff, #24292e);--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;color:light-dark(#24292e, #e1e4e8);--shiki-light:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Przykład: Deployment w Kubernetes\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">apiVersion\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">apps/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">kind\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Deployment\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">metadata\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">api-deployment\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">spec\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  replicas\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#005CC5, #79B8FF);--shiki-light:#005CC5;--shiki-dark:#79B8FF\">3\u003C/span>\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # Chcemy 3 instancje\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  selector\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    matchLabels\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">      app\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">api\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  template\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    metadata\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">      labels\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        app\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">api\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    spec\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">      containers\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">api\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        image\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">myregistry/api:v1.2.3\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        ports\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">        - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">containerPort\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#005CC5, #79B8FF);--shiki-light:#005CC5;--shiki-dark:#79B8FF\">3000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        resources\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">          requests\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">            memory\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"128Mi\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">            cpu\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"100m\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">          limits\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">            memory\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"512Mi\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">            cpu\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"500m\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Kubernetes jest potężny, ale ma wysoką krzywą uczenia się i znaczną złożoność operacyjną. Dla małych projektów to zdecydowanie overkill — Docker Compose lub zarządzane platformy jak Railway, Render czy \u003Ca href=\"http://Fly.io\" target=\"_blank\" rel=\"noopener noreferrer\">Fly.io\u003C/a> będą znacznie lepszym wyborem.\u003C/p>\n\u003Ch2 id=\"chmura-vs-vps-gdzie-uruchomic-aplikacje\" tabindex=\"-1\">Chmura vs. VPS — gdzie uruchomić aplikację?\u003C/h2>\n\u003Cp>Gdy Twoja aplikacja jest gotowa do wdrożenia, stoisz przed pytaniem: gdzie ją uruchomić? Rynek oferuje dwa główne podejścia: \u003Cstrong>chmurę publiczną\u003C/strong> i \u003Cstrong>prywatne serwery VPS\u003C/strong>.\u003C/p>\n\u003Ch3 id=\"rozwiazania-chmurowe\" tabindex=\"-1\">Rozwiązania chmurowe\u003C/h3>\n\u003Cp>\u003Cstrong>Chmura publiczna\u003C/strong> to infrastruktura udostępniana przez duże firmy — Amazon Web Services (AWS), Google Cloud Platform (GCP) i Microsoft Azure to trójka dominująca rynek. Oprócz nich istnieje wiele platform wyższego poziomu jak Vercel, Netlify, Railway czy \u003Ca href=\"http://Fly.io\" target=\"_blank\" rel=\"noopener noreferrer\">Fly.io\u003C/a>, które abstrahują dużą część złożoności.\u003C/p>\n\u003Cp>Chmura oferuje kilka unikalnych możliwości. \u003Cstrong>Skalowanie na żądanie\u003C/strong> — możesz zwiększyć zasoby w minutach, gdy nagle pojawi się 10x więcej ruchu, i zmniejszyć je gdy ruch opada, płacąc tylko za to co zużywasz. \u003Cstrong>Managed services\u003C/strong> — zamiast samodzielnie konfigurować i utrzymywać bazę danych, cache, kolejki wiadomości czy CDN, możesz użyć gotowych, zarządzanych usług: Amazon RDS, ElastiCache, SQS. Nie martwisz się o patche bezpieczeństwa, backupy, failover — dostawca robi to za Ciebie. \u003Cstrong>Globalna infrastruktura\u003C/strong> — możesz uruchomić aplikację w regionach na całym świecie, minimalizując opóźnienia dla użytkowników z różnych kontynentów.\u003C/p>\n\u003Cp>Główna wada chmury to \u003Cstrong>koszt\u003C/strong>. Przy nieprzemyślanym użyciu rachunki mogą być zaskakująco wysokie, szczególnie w AWS, gdzie model płatności jest bardzo granularny. Drugi problem to \u003Cstrong>vendor lock-in\u003C/strong> — gdy zaczniesz głęboko używać specyficznych usług AWS (Lambda, DynamoDB, SQS), migracja do innego dostawcy staje się kosztowna.\u003C/p>\n\u003Ch3 id=\"vps-klasyczna-alternatywa\" tabindex=\"-1\">VPS — klasyczna alternatywa\u003C/h3>\n\u003Cp>\u003Cstrong>VPS\u003C/strong> \u003Cem>(Virtual Private Server)\u003C/em> to wirtualna maszyna na serwerze fizycznym, którą wynajmujesz od dostawcy — DigitalOcean, Hetzner, Linode/Akamai, OVH. Dostajesz serwer z określoną ilością CPU, RAM i dysku, płacisz stałą miesięczną stawkę i robisz na nim co chcesz.\u003C/p>\n\u003Cp>VPS jest tańszy w przewidywalnych obciążeniach — za $20-50 miesięcznie możesz mieć solidny serwer dla aplikacji obsługującej tysiące użytkowników dziennie. Masz pełną kontrolę nad środowiskiem i wiesz dokładnie ile zapłacisz na końcu miesiąca.\u003C/p>\n\u003Cp>Wadą jest to, że \u003Cstrong>całe zarządzanie infrastrukturą leży po Twojej stronie\u003C/strong>. Aktualizacje systemu, konfiguracja firewalla, certyfikaty SSL, backupy, monitoring — to wszystko Twoja odpowiedzialność. Nie ma wbudowanego skalowania — jeśli potrzebujesz więcej zasobów, musisz ręcznie zmienić plan serwera lub dodać nowe maszyny i skonfigurować load balancer.\u003C/p>\n\u003Ch3 id=\"jak-wybrac\" tabindex=\"-1\">Jak wybrać?\u003C/h3>\n\u003Cp>Praktyczna heurystyka: jeśli dopiero zaczynasz lub masz mały projekt o przewidywalnym ruchu, \u003Cstrong>VPS od Hetzner jest prawdopodobnie najlepszym wyborem\u003C/strong> — stosunek ceny do wydajności jest wybitny, a prostota zarządzania wystarczająca. Gdy aplikacja rośnie, ruch staje się nieprzewidywalny lub potrzebujesz zaawansowanych managed services, warto rozważyć chmurę. Wiele firm korzysta z hybrydy: baza danych na managed RDS w AWS, aplikacja na tańszych VPS-ach od Hetzner.\u003C/p>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Aspekt\u003C/th>\n\u003Cth>VPS (np. Hetzner)\u003C/th>\n\u003Cth>Chmura (np. AWS)\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>Koszt (stały ruch)\u003C/td>\n\u003Ctd>Niski, przewidywalny\u003C/td>\n\u003Ctd>Wyższy, może zaskoczyć\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Koszt (ruch skokowy)\u003C/td>\n\u003Ctd>Trzeba nadprowizjonować\u003C/td>\n\u003Ctd>Płacisz tylko za zużycie\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Zarządzanie\u003C/td>\n\u003Ctd>Ręczne, pełna kontrola\u003C/td>\n\u003Ctd>Managed services dostępne\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Skalowanie\u003C/td>\n\u003Ctd>Manualne / ograniczone\u003C/td>\n\u003Ctd>Automatyczne, elastyczne\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Krzywa uczenia\u003C/td>\n\u003Ctd>Niska\u003C/td>\n\u003Ctd>Wysoka dla zaawansowanych usług\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\n\u003Ch2 id=\"deployment-i-cicd-jak-wdrazac-aplikacje-bez-bolu\" tabindex=\"-1\">Deployment i CI/CD — jak wdrażać aplikacje bez bólu\u003C/h2>\n\u003Cp>\u003Cstrong>Deployment\u003C/strong> to proces wdrożenia nowej wersji aplikacji na serwer produkcyjny. Zrobiony ręcznie — przez kopiowanie plików przez FTP, ręczne uruchamianie komend na serwerze — jest wolny, podatny na błędy i stresujący. Nowoczesne podejście to automatyzacja tego procesu przez \u003Cstrong>CI/CD\u003C/strong>.\u003C/p>\n\u003Ch3 id=\"cicd-co-to-wasciwie-znaczy\" tabindex=\"-1\">CI/CD — co to właściwie znaczy?\u003C/h3>\n\u003Cp>\u003Cstrong>CI\u003C/strong> \u003Cem>(Continuous Integration)\u003C/em> to praktyka częstego scalania zmian kodu do głównej gałęzi repozytorium, automatycznie uruchamiając przy tym testy. Celem jest wczesne wykrycie problemów — zamiast integrować zmiany od wielu developerów raz na tydzień i odkrywać konflikty, robisz to wielokrotnie dziennie.\u003C/p>\n\u003Cp>\u003Cstrong>CD\u003C/strong> może oznaczać dwie rzeczy: \u003Cem>Continuous Delivery\u003C/em> — każda zmiana jest automatycznie przygotowywana do wdrożenia, ale wdrożenie wymaga manualnego potwierdzenia, albo \u003Cem>Continuous Deployment\u003C/em> — każda zmiana przechodzi przez pipeline i trafia automatycznie na produkcję bez interwencji człowieka.\u003C/p>\n\u003Cp>Popularną platformą CI/CD jest \u003Cstrong>GitHub Actions\u003C/strong>, ale są też GitLab CI, CircleCI, Jenkins i wiele innych. Oto jak może wyglądać prosty pipeline:\u003C/p>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:light-dark(#fff, #24292e);--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;color:light-dark(#24292e, #e1e4e8);--shiki-light:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># .github/workflows/deploy.yml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Deploy to Production\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#005CC5, #79B8FF);--shiki-light:#005CC5;--shiki-dark:#79B8FF\">on\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  push\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    branches\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: [\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">main\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">jobs\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  test\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    runs-on\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">ubuntu-latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    steps\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">uses\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">actions/checkout@v4\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Setup Node.js\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        uses\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">actions/setup-node@v4\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        with\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">          node-version\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'20'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">          \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Install dependencies\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">npm ci\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">        \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Run tests\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">npm test\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">        \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Run linter\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">npm run lint\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">  deploy\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    needs\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">test\u003C/span>\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # Deploy tylko jeśli testy przeszły\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    runs-on\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">ubuntu-latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">    steps\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">uses\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">actions/checkout@v4\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Build Docker image\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">docker build -t myapp:${{ github.sha }} .\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">        \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Push to registry\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">|\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">          docker tag myapp:${{ github.sha }} registry.io/myapp:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">          docker push registry.io/myapp:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">          \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      - \u003C/span>\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">name\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">Deploy to server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#22863A, #85E89D);--shiki-light:#22863A;--shiki-dark:#85E89D\">        run\u003C/span>\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">|\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">          ssh user@myserver.com \"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">            docker pull registry.io/myapp:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">            docker-compose -f /app/docker-compose.prod.yml up -d\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">          \"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Teraz za każdym razem gdy pushujemy kod do gałęzi \u003Ccode>main\u003C/code>, GitHub automatycznie uruchamia testy i jeśli przejdą — wdraża nową wersję. Zero ręcznej pracy.\u003C/p>\n\u003Ch3 id=\"strategie-wdrozen-zero-downtime\" tabindex=\"-1\">Strategie wdrożeń — zero downtime\u003C/h3>\n\u003Cp>Naiwne wdrożenie wygląda tak: zatrzymujesz starą wersję, uruchamiasz nową. W tym czasie aplikacja jest niedostępna. Dla poważnych serwisów to nie do zaakceptowania.\u003C/p>\n\u003Cp>\u003Cstrong>Rolling deployment\u003C/strong> polega na stopniowym zastępowaniu instancji starej wersji nowymi. W danym momencie część serwerów obsługuje starą wersję, część nową, a ruch jest rozdzielany przez load balancer. Użytkownicy nie odczuwają przestoju.\u003C/p>\n\u003Cp>\u003Cstrong>Blue-green deployment\u003C/strong> to utrzymywanie dwóch identycznych środowisk — &quot;niebieskiego&quot; (aktualna produkcja) i &quot;zielonego&quot; (nowa wersja). Wdrażasz na zielone, testujesz, a potem jednym przełączeniem w load balancerze przenosisz cały ruch z niebieskiego na zielone. Rollback w razie problemów to kolejne jedno przełączenie — natychmiastowe.\u003C/p>\n\u003Cp>\u003Cstrong>Canary deployment\u003C/strong> to ostrożne wypuszczanie nowej wersji do małego procentu użytkowników — powiedzmy 5%. Monitorujesz błędy i metryki. Jeśli wszystko jest okej, stopniowo zwiększasz procent. Jeśli pojawi się problem, odwracasz zmianę dotykając tylko 5% użytkowników.\u003C/p>\n\u003Ch2 id=\"skalowanie-optymalizacja-i-srodowisko-produkcyjne\" tabindex=\"-1\">Skalowanie, optymalizacja i środowisko produkcyjne\u003C/h2>\n\u003Ch3 id=\"skalowanie-poziome-vs-pionowe\" tabindex=\"-1\">Skalowanie — poziome vs. pionowe\u003C/h3>\n\u003Cp>Gdy aplikacja nie nadąża z obsługą rosnącego ruchu, masz dwa podejścia do skalowania.\u003C/p>\n\u003Cp>\u003Cstrong>Skalowanie pionowe\u003C/strong> \u003Cem>(vertical scaling / scale up)\u003C/em> oznacza danie serwerowi więcej zasobów — więcej RAM, szybszy CPU, więcej dysków. To proste i nie wymaga zmian w kodzie, ale ma twardy limit — w końcu nie możesz dodać nieskończenie dużo zasobów do jednej maszyny, a też jest dość drogie.\u003C/p>\n\u003Cp>\u003Cstrong>Skalowanie poziome\u003C/strong> \u003Cem>(horizontal scaling / scale out)\u003C/em> to uruchamianie wielu instancji aplikacji i rozdzielanie ruchu między nimi przez \u003Cstrong>load balancer\u003C/strong>. To bardziej złożone — aplikacja musi być bezstanowa (nie przechowywać sesji użytkownika lokalnie na serwerze) albo używać zewnętrznego magazynu stanu jak Redis — ale daje praktycznie nieograniczoną skalowalność.\u003C/p>\n\u003Cp>Nowoczesne aplikacje projektuje się z myślą o skalowaniu poziomym. Zasada brzmi: \u003Cem>treat servers like cattle, not pets\u003C/em> — traktuj serwery jak bydło, nie jak zwierzęta domowe. Każdy serwer jest wymienny, może paść i zostać zastąpiony nowym automatycznie.\u003C/p>\n\u003Ch3 id=\"srodowisko-developerskie-vs-produkcyjne\" tabindex=\"-1\">Środowisko developerskie vs. produkcyjne\u003C/h3>\n\u003Cp>Różnice między środowiskiem lokalnym a produkcyjnym to jedno z częstszych źródeł problemów. Ważne jest by je rozumieć i zarządzać nimi świadomie.\u003C/p>\n\u003Cp>Na \u003Cstrong>środowisku developerskim\u003C/strong> priorytetem jest szybkość iteracji: hot reloading (zmiany w kodzie widoczne natychmiast), verbose logging (szczegółowe logi błędów), wyłączone cache i optymalizacje (żeby widzieć aktualne dane), lokalna baza danych z danymi testowymi, zmienne środowiskowe wskazujące na lokalne serwisy.\u003C/p>\n\u003Cp>Na \u003Cstrong>środowisku produkcyjnym\u003C/strong> priorytety są zupełnie inne: zminimalizowany i zoptymalizowany kod (tree shaking, minifikacja, kompresja), agresywne cache (CDN dla statycznych zasobów, cache na poziomie bazy danych), tylko niezbędne logi (logowanie każdego requestu na dużym ruchu zabija wydajność), środowiskowe sekrety zarządzane przez vault lub secrets manager, monitoring i alerty.\u003C/p>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:light-dark(#fff, #24292e);--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;color:light-dark(#24292e, #e1e4e8);--shiki-light:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># .env.development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">NODE_ENV\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">LOG_LEVEL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">debug\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">DATABASE_URL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">postgres://localhost:5432/myapp_dev\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">CACHE_TTL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">0\u003C/span>\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # Wyłączone cache w devie\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\"># .env.production\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">NODE_ENV\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">production\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">LOG_LEVEL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">warn\u003C/span>\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # Tylko ostrzeżenia i błędy\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">DATABASE_URL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">postgres://prod-db.internal:5432/myapp\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:light-dark(#24292E, #E1E4E8);--shiki-light:#24292E;--shiki-dark:#E1E4E8\">CACHE_TTL\u003C/span>\u003Cspan style=\"color:light-dark(#D73A49, #F97583);--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C/span>\u003Cspan style=\"color:light-dark(#032F62, #9ECBFF);--shiki-light:#032F62;--shiki-dark:#9ECBFF\">3600\u003C/span>\u003Cspan style=\"color:light-dark(#6A737D, #6A737D);--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # Cache na godzinę\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Kluczowe jest też rozdzielenie konfiguracji od kodu. \u003Cstrong>Nigdy\u003C/strong> nie trzymaj haseł, kluczy API, connection stringów w repozytorium Git. Używaj zmiennych środowiskowych, dedykowanych secret managerów (HashiCorp Vault, AWS Secrets Manager) lub platform, które zarządzają tym za Ciebie (Vercel, Railway, Heroku mają wbudowaną obsługę secretów).\u003C/p>\n\u003Ch3 id=\"monitoring-i-obserwowalnosc\" tabindex=\"-1\">Monitoring i obserwowalność\u003C/h3>\n\u003Cp>Aplikacja produkcyjna, której nie monitorujesz, to aplikacja, której problemów nie znasz. \u003Cstrong>Obserwowalność\u003C/strong> \u003Cem>(observability)\u003C/em> to zdolność do rozumienia wewnętrznego stanu systemu na podstawie jego zewnętrznych wyjść. Składają się na nią trzy filary:\u003C/p>\n\u003Cp>\u003Cstrong>Logi\u003C/strong> to sekwencyjny zapis zdarzeń w systemie. Na produkcji używaj strukturyzowanych logów w formacie JSON, agreguj je w jednym miejscu (Datadog, Grafana Loki, CloudWatch) i definiuj alerty na krytyczne błędy. Dobry log zawiera timestamp, poziom (INFO/WARN/ERROR), wiadomość, request ID (pozwala śledzić jeden request przez wiele serwisów) i kontekst.\u003C/p>\n\u003Cp>\u003Cstrong>Metryki\u003C/strong> to liczby mierzone w czasie: liczba requestów na sekundę, czas odpowiedzi (p95, p99), użycie CPU i RAM, rozmiar kolejek. Prometheus z Grafaną to popularny, open-source'owy stack do zbierania i wizualizacji metryk.\u003C/p>\n\u003Cp>\u003Cstrong>Tracing\u003C/strong> to śledzenie jednego requestu przez wszystkie komponenty systemu — niezbędne w architekturze mikroserwisów. Gdy request przechodzi przez 6 serwisów, distributed tracing pozwala zobaczyć gdzie jest wąskie gardło i gdzie pojawiają się błędy.\u003C/p>\n\u003Ch2 id=\"podsumowanie-architektura-to-duga-gra\" tabindex=\"-1\">Podsumowanie — architektura to długa gra\u003C/h2>\n\u003Cp>Architektura aplikacji to nie jednorazowa decyzja — to zbiór wyborów, które ewoluują razem z produktem. Żadne rozwiązanie nie jest idealne dla każdego kontekstu i każdej skali.\u003C/p>\n\u003Cp>Jeśli miałbym wyciągnąć z tego artykułu kilka najważniejszych wniosków, brzmiałyby one tak. \u003Cstrong>Zacznij prosto\u003C/strong> — monolit, jeden VPS, ręczny deployment jest lepszy niż przekomplikowana architektura mikroserwisów, którą trudno utrzymać i debugować przy projekcie z 3-osobowym zespołem. \u003Cstrong>Konteneryzuj od początku\u003C/strong> — Docker usuwa klasyczny problem &quot;u mnie działa&quot; i ułatwia późniejsze przejście do bardziej złożonej infrastruktury. \u003Cstrong>Automatyzuj deployment\u003C/strong> — CI/CD to nie luksus ale konieczność; każda minuta poświęcona na ręczne wdrożenia to strata czasu i źródło błędów. \u003Cstrong>Rozdzielaj konfigurację od kodu\u003C/strong> — sekrety w repozytorium to bomba z opóźnionym zapłonem. \u003Cstrong>Monitoruj produkcję\u003C/strong> — aplikacja bez monitoringu to aplikacja, o której problemach dowiadujesz się od użytkowników.\u003C/p>\n\u003Cp>Architektura to fundament. Nie widać jej gdy jest dobra — ale bardzo widać gdy jest zła. Warto inwestować czas w jej przemyślenie, nawet jeśli na początku wydaje się to spowalniać development. W dłuższej perspektywie dobra architektura pozwala rozwijać produkt szybciej, pewniej i z mniejszym stresem.\u003C/p>\n",{"en":24,"pl":95},[25,29,32,35,39,42,45,48,52,55,59,62,65,68,72,75,78,82,85,88,91],{"id":26,"title":27,"mainLevel":28,"subLevel":14},"application-architecture-the-foundation-of-every-project","Application architecture — the foundation of every project",1,{"id":30,"title":31,"mainLevel":18,"subLevel":14},"frontend-backend-and-separation-of-concerns","Frontend, backend, and separation of concerns",{"id":33,"title":34,"mainLevel":18,"subLevel":28},"bff-backend-for-frontend","BFF — Backend for Frontend",{"id":36,"title":37,"mainLevel":38,"subLevel":14},"monolith-vs-microservices-the-great-architecture-dilemma","Monolith vs. microservices — the great architecture dilemma",3,{"id":40,"title":41,"mainLevel":38,"subLevel":28},"monolith-simple-strength","Monolith — simple strength",{"id":43,"title":44,"mainLevel":38,"subLevel":18},"microservices-divided-strength","Microservices — divided strength",{"id":46,"title":47,"mainLevel":38,"subLevel":38},"when-monolith-when-microservices","When monolith, when microservices?",{"id":49,"title":50,"mainLevel":51,"subLevel":14},"containerization-docker-and-the-revolution-in-environments","Containerization — Docker and the revolution in environments",4,{"id":53,"title":54,"mainLevel":51,"subLevel":28},"kubernetes-orchestration-for-real","Kubernetes — orchestration for real",{"id":56,"title":57,"mainLevel":58,"subLevel":14},"cloud-vs-vps-where-to-run-the-application","Cloud vs. VPS — where to run the application?",5,{"id":60,"title":61,"mainLevel":58,"subLevel":28},"cloud-solutions","Cloud solutions",{"id":63,"title":64,"mainLevel":58,"subLevel":18},"vps-the-classic-alternative","VPS — the classic alternative",{"id":66,"title":67,"mainLevel":58,"subLevel":38},"how-to-choose","How to choose?",{"id":69,"title":70,"mainLevel":71,"subLevel":14},"deployment-and-cicd-how-to-deploy-applications-without-pain","Deployment and CI/CD — how to deploy applications without pain",6,{"id":73,"title":74,"mainLevel":71,"subLevel":28},"cicd-what-does-it-actually-mean","CI/CD — what does it actually mean?",{"id":76,"title":77,"mainLevel":71,"subLevel":18},"deployment-strategies-zero-downtime","Deployment strategies — zero downtime",{"id":79,"title":80,"mainLevel":81,"subLevel":14},"scaling-optimization-and-production-environment","Scaling, optimization, and production environment",7,{"id":83,"title":84,"mainLevel":81,"subLevel":28},"scaling-horizontal-vs-vertical","Scaling — horizontal vs. vertical",{"id":86,"title":87,"mainLevel":81,"subLevel":18},"development-vs-production-environment","Development vs. production environment",{"id":89,"title":90,"mainLevel":81,"subLevel":38},"monitoring-and-observability","Monitoring and observability",{"id":92,"title":93,"mainLevel":94,"subLevel":14},"summary-architecture-is-a-long-game","Summary — architecture is a long game",8,[96,99,102,103,106,109,112,115,118,121,124,127,130,133,136,139,142,145,148,151,154],{"id":97,"title":98,"mainLevel":28,"subLevel":14},"architektura-aplikacji-fundament-kazdego-projektu","Architektura aplikacji — fundament każdego projektu",{"id":100,"title":101,"mainLevel":18,"subLevel":14},"frontend-backend-i-podzia-obowiazkow","Frontend, backend i podział obowiązków",{"id":33,"title":34,"mainLevel":18,"subLevel":28},{"id":104,"title":105,"mainLevel":38,"subLevel":14},"monolit-vs-mikroserwisy-wielki-dylemat-architektury","Monolit vs. mikroserwisy — wielki dylemat architektury",{"id":107,"title":108,"mainLevel":38,"subLevel":28},"monolit-prosta-sia","Monolit — prosta siła",{"id":110,"title":111,"mainLevel":38,"subLevel":18},"mikroserwisy-podzielona-sia","Mikroserwisy — podzielona siła",{"id":113,"title":114,"mainLevel":38,"subLevel":38},"kiedy-monolit-kiedy-mikroserwisy","Kiedy monolit, kiedy mikroserwisy?",{"id":116,"title":117,"mainLevel":51,"subLevel":14},"konteneryzacja-docker-i-rewolucja-w-srodowiskach","Konteneryzacja — Docker i rewolucja w środowiskach",{"id":119,"title":120,"mainLevel":51,"subLevel":28},"kubernetes-orkiestracja-na-powaznie","Kubernetes — orkiestracja na poważnie",{"id":122,"title":123,"mainLevel":58,"subLevel":14},"chmura-vs-vps-gdzie-uruchomic-aplikacje","Chmura vs. VPS — gdzie uruchomić aplikację?",{"id":125,"title":126,"mainLevel":58,"subLevel":28},"rozwiazania-chmurowe","Rozwiązania chmurowe",{"id":128,"title":129,"mainLevel":58,"subLevel":18},"vps-klasyczna-alternatywa","VPS — klasyczna alternatywa",{"id":131,"title":132,"mainLevel":58,"subLevel":38},"jak-wybrac","Jak wybrać?",{"id":134,"title":135,"mainLevel":71,"subLevel":14},"deployment-i-cicd-jak-wdrazac-aplikacje-bez-bolu","Deployment i CI/CD — jak wdrażać aplikacje bez bólu",{"id":137,"title":138,"mainLevel":71,"subLevel":28},"cicd-co-to-wasciwie-znaczy","CI/CD — co to właściwie znaczy?",{"id":140,"title":141,"mainLevel":71,"subLevel":18},"strategie-wdrozen-zero-downtime","Strategie wdrożeń — zero downtime",{"id":143,"title":144,"mainLevel":81,"subLevel":14},"skalowanie-optymalizacja-i-srodowisko-produkcyjne","Skalowanie, optymalizacja i środowisko produkcyjne",{"id":146,"title":147,"mainLevel":81,"subLevel":28},"skalowanie-poziome-vs-pionowe","Skalowanie — poziome vs. pionowe",{"id":149,"title":150,"mainLevel":81,"subLevel":18},"srodowisko-developerskie-vs-produkcyjne","Środowisko developerskie vs. produkcyjne",{"id":152,"title":153,"mainLevel":81,"subLevel":38},"monitoring-i-obserwowalnosc","Monitoring i obserwowalność",{"id":155,"title":156,"mainLevel":94,"subLevel":14},"podsumowanie-architektura-to-duga-gra","Podsumowanie — architektura to długa gra",1785418086796]