<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bilaniuc Dragos</title>
    <description>The latest articles on DEV Community by Bilaniuc Dragos (@dragosbln).</description>
    <link>https://dev.to/dragosbln</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F667037%2F9cecb184-ee2a-4249-9a4b-09008692eb32.jpeg</url>
      <title>DEV Community: Bilaniuc Dragos</title>
      <link>https://dev.to/dragosbln</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dragosbln"/>
    <language>en</language>
    <item>
      <title>Securing auth in a large-scale production system: three industry-standard architectures — and why none survived a closer look</title>
      <dc:creator>Bilaniuc Dragos</dc:creator>
      <pubDate>Tue, 26 May 2026 09:47:36 +0000</pubDate>
      <link>https://dev.to/dragosbln/securing-auth-in-a-large-scale-production-system-three-industry-standard-architectures-and-why-279b</link>
      <guid>https://dev.to/dragosbln/securing-auth-in-a-large-scale-production-system-three-industry-standard-architectures-and-why-279b</guid>
      <description>&lt;p&gt;&lt;em&gt;A case study in why the verdict on an architecture decision can shift entirely once you dive into implementation details — using auth security on a large Next.js + AWS system as the vehicle. This article walks the three architectural paths we considered — plus a fourth option that, in this context, won.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Context: a sensitive problem in a large scale system
&lt;/h2&gt;

&lt;p&gt;The system: a large multi-frontend production stack. Multiple Next.js apps spread across subdomains, 100+ backend microservices, AWS Cognito for identity, API Gateway in front of the backend, downstream APIs expecting &lt;code&gt;Authorization: Bearer &amp;lt;id_token&amp;gt;&lt;/code&gt; on every request.&lt;/p&gt;

&lt;p&gt;The finding: a penetration test flags that our Cognito tokens — ID, access, refresh — are stored in non-HttpOnly cookies. Client-side JavaScript can read them. Any successful XSS exfiltrates them. Any leaked refresh token gives an attacker effectively indefinite access.&lt;/p&gt;

&lt;p&gt;Here's what that looks like in flow form — the current client-side API call pattern, with the moment of vulnerability highlighted:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6wu7d7zr1p2sriqdrxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6wu7d7zr1p2sriqdrxf.png" alt="Current Implementation — Direct Client-to-Backend with JS-Accessible Tokens" width="799" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Three things worth noticing before we go further. First, this flow is cheap — the client calls the backend directly, no proxy layer in the path, every component doing the minimum it has to. Second, the entire vulnerability is concentrated in the single step where browser-side code reads the token out of document.cookie to attach it to the outbound request. Third, every alternative we'll walk through changes the shape of that single moment — and in doing so, ripples through every other component on the diagram.&lt;/p&gt;

&lt;p&gt;The shape of the fix is well-known: tokens should not be JS-readable. Move them off the client.&lt;/p&gt;

&lt;p&gt;So why are we writing a 3,500-word article about it?&lt;/p&gt;

&lt;p&gt;Because auth in a system like this isn't a feature. It's a hot path — twice. It's the entry point to the system, and then it's a participant in every API call that follows. The architecture choice you make doesn't just impact "the login screen." It impacts every request, every page render, every cost line item, every incident postmortem for the foreseeable future.&lt;/p&gt;

&lt;p&gt;That's the kind of problem where the obvious architectural answer is the dangerous one — not because it's wrong, but because it's incomplete. The shape is right; the implementation cost can take you over the edge.&lt;/p&gt;

&lt;p&gt;This article walks four architectural paths to fix the same vulnerability in the same system. Each path is sound in isolation. Each path's verdict shifts — sometimes inverts — once you stop thinking at the architecture level and start thinking at the implementation level.&lt;/p&gt;

&lt;p&gt;The stack details are the vehicle. The cargo is the thinking pattern: &lt;strong&gt;architectural thinking alone won't tell you which of these four paths is right. Implementation depth will.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The "obvious" answer, and why to distrust it
&lt;/h2&gt;

&lt;p&gt;The chain of obvious reasoning:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tokens accessible to JavaScript are vulnerable to XSS exfiltration.&lt;/li&gt;
&lt;li&gt;Therefore, move tokens out of JavaScript's reach.&lt;/li&gt;
&lt;li&gt;Therefore, use HttpOnly cookies, set by the server, never read by the client.&lt;/li&gt;
&lt;li&gt;Done.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the &lt;em&gt;shape&lt;/em&gt; level, this is correct.&lt;/p&gt;

&lt;p&gt;The trouble is that step 4. "Done" is not done — it's actually doing about 90% of the work in that argument. "Done" implies the implementation falls out cleanly. It almost never does.&lt;/p&gt;

&lt;p&gt;The architectural move is to refuse "done" as an output until you've answered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How does the client-side code now authenticate API calls it used to authenticate directly?&lt;/li&gt;
&lt;li&gt;How does the backend now extract a credential it used to receive in a known format?&lt;/li&gt;
&lt;li&gt;How does the system refresh tokens that can no longer be seen by the code that previously refreshed them?&lt;/li&gt;
&lt;li&gt;What's the new attack surface? (HttpOnly cookies close XSS; they open CSRF.)&lt;/li&gt;
&lt;li&gt;What does the cost model look like at production scale?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of those questions has multiple architecturally-valid answers. Each answer creates a different system. The point of the analysis isn't to find &lt;em&gt;an&lt;/em&gt; answer — it's to walk each answer to its third-order consequences before picking.&lt;/p&gt;

&lt;p&gt;Let's do that.&lt;/p&gt;




&lt;h2&gt;
  
  
  The constraint stack
&lt;/h2&gt;

&lt;p&gt;The constraints below are real — pulled from the actual system. They're what every architectural option gets weighed against. The discipline here is &lt;em&gt;map options against constraints, not against feature checklists.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Frontend framework.&lt;/strong&gt; Next.js App Router, heavy use of Server Components, hybrid client-server data fetching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Downstream contract.&lt;/strong&gt; ~100+ backend microservices, all expecting &lt;code&gt;Authorization: Bearer &amp;lt;id_token&amp;gt;&lt;/code&gt;. The API Gateway in front of them validates JWTs via its built-in authorizer reading the &lt;code&gt;Authorization&lt;/code&gt; header. Changing this contract means changing it across all 100+ services in a coordinated manner. Doing it in fewer than all of them is not an option — the contract is uniform on purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Hosting cost model.&lt;/strong&gt; The Next.js apps run on Vercel. Vercel bills serverless functions by the &lt;em&gt;wall clock time&lt;/em&gt; of every request — including the time spent waiting on a slow downstream call. A 5-second hung backend response gets billed for 5 seconds of compute, every time it happens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Client/server call ratio.&lt;/strong&gt; Roughly 65-70% of API calls in the system are made directly from the browser (client components, after-hydration data fetches). The remaining 30-35% happen server-side during SSR. Any architecture that proxies "all client calls through the server" effectively doubles the proxied request volume.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Token characteristics.&lt;/strong&gt; Cognito JWTs are large — ID tokens commonly run 1-2KB, sometimes more depending on groups and claims. Browser cookie size limits sit at 4KB per cookie, and total request header limits (the source of HTTP 431 errors) sit at 8KB on many gateways. Putting multiple Cognito tokens in cookies and sending them on every request is a known production failure mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Vendor library maturity.&lt;/strong&gt; AWS Amplify v6 supports HttpOnly cookies for Next.js — but only via an experimental server-side auth feature, and only when paired with Cognito Managed Login.&lt;/p&gt;

&lt;p&gt;That's the stack. Every option below has to survive it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Path 1: Next.js BFF proxy
&lt;/h2&gt;

&lt;p&gt;The pattern most commonly recommended in the Next.js ecosystem, and the one AWS Premium Support proposed in the first round of their guidance. It's also the default shape that libraries like Auth.js (formerly NextAuth) push you toward when wrapping OAuth providers — manage session cookies on the server, proxy token-bearing calls through Next.js route handlers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The shape:&lt;/strong&gt; All client-side API calls stop going directly to the backend. Instead, they hit Next.js route handlers (or Server Actions). Those handlers read tokens from HttpOnly cookies — which they can, because they're server-side — and forward the request to the backend with the &lt;code&gt;Authorization: Bearer&lt;/code&gt; header attached.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ailc41s0savkgndsgxo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ailc41s0savkgndsgxo.png" alt="Path 1 — Next.js BFF Proxy" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The architectural appeal.&lt;/strong&gt; Clean. Well-documented. Vendor-blessed. The pattern most public material recommends. Tokens never touch the client; the downstream contract doesn't change; the API Gateway's existing JWT authorizer keeps working.&lt;/p&gt;

&lt;p&gt;At the architecture level, this looks like the right answer. It is, in fact, the right answer for many systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it stops looking right — implementation level.&lt;/strong&gt; Two things surface as you zoom in:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The cost model breaks.&lt;/em&gt; Recall constraints #3 and #4. We have a hosting model that bills for wall-clock wait time, and we'd be putting 65-70% of API traffic that previously bypassed Vercel directly &lt;em&gt;through&lt;/em&gt; Vercel. Every slow backend call now costs us twice — once for the original execution time, once for the time the Vercel function spends waiting. A backend incident where calls take 30 seconds to time out becomes a Vercel bill incident.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Vercel lock-in becomes structural.&lt;/em&gt; In the BFF model, 100% of API traffic flows through Next.js route handlers on Vercel — making Vercel part of every API call's critical path, and shaping the architecture around Vercel-optimized patterns. Any future migration to a different host (for cost reasons, feature reasons, or just optionality) stops being a packaging change and becomes a real re-architecture. Vercel's billing model has, at this scale, already produced unwelcome surprises; locking the auth hot path to a single hosting vendor compounds that exposure rather than reducing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verdict shift.&lt;/strong&gt; Strong default. Wrong for &lt;em&gt;this&lt;/em&gt; stack — the cost surface and the vendor lock-in are the real disqualifiers; everything else is downstream of them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Path 2: Token-broker BFF with session DB
&lt;/h2&gt;

&lt;p&gt;A variant that escapes Vercel by introducing a dedicated AWS-native proxy. The browser holds an HttpOnly session cookie (opaque); a Lambda sits in front of the backend, reads the cookie, looks the session up in a database, retrieves the Cognito token, and forwards the request with the Bearer header attached.&lt;/p&gt;

&lt;p&gt;This is essentially the architecture that &lt;strong&gt;Better Auth&lt;/strong&gt; promotes when it's wired up to an external OAuth provider like Cognito: a server-side session store with the provider's tokens held inside it, and the browser carrying only an opaque session reference. Better Auth also supports a stateless variant — where the session is encrypted directly into the cookie and the DB lookup disappears — which trades the database hot path for cookie-size and key-rotation problems. We'll focus on the DB-backed shape, as it's the one most production deployments converge on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcdv48xxobqzniwcb88ew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcdv48xxobqzniwcb88ew.png" alt="Path 2 — Token Broker with Session DB" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The architectural appeal.&lt;/strong&gt; Full session control — you can revoke individual sessions, track devices, enforce idle timeouts, support multiple identity providers without each one polluting the cookie payload. Vercel cost goes away. The downstream contract is preserved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it stops looking right — implementation level.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We now own the entire auth substrate.&lt;/em&gt; The biggest hidden cost in this path isn't in any individual diagram; it's in the operational total. A new database layer to provision, scale, and back up. A new session mechanism to write, test, patch, and version. A new piece of critical infrastructure to bring into the on-call rotation. Security updates and resilience improvements that previously came "for free" from the vendor stack — Amplify patches, Cognito-side improvements — now have to be applied (or replicated) by us. Auth is the part of a system you most want operated by people who specialize in operating auth; this path moves you in the opposite direction.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The session DB becomes a hot path.&lt;/em&gt; Every API call now pays a DB lookup latency. Even at with high-throughput DBs (like Dynamo) that's added to every request that crosses the system boundary, and the database becomes the system's availability ceiling for any authenticated traffic.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Database choice is a one-way door.&lt;/em&gt; DynamoDB is the AWS-native default, but if you ever need a relational session model — joins, audit trails, complex revocation rules — you're either retrofitting an inappropriate store or migrating. ElastiCache buys sub-millisecond reads but adds VPC complexity. Aurora + RDS Proxy buys SQL but needs explicit guard-rails against connection storms. Each is sticky once chosen.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Observability fragments.&lt;/em&gt; There's now an extra hop, possibly in a different language, in a different deployment unit. Distributed tracing has to follow it. Failures in the broker look different from failures in the backend — and that distinction matters during the worst incident calls, when you need to localize a problem in under five minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is where it's worth distinguishing stateful complexity from feature complexity.&lt;/strong&gt; Both Path 1 and Path 2 add complexity, but in different shapes. Path 1's complexity is &lt;em&gt;operational&lt;/em&gt; — a new layer that needs to scale and stay up. Path 2's complexity is &lt;em&gt;stateful and ownership-shaped&lt;/em&gt; — a new system-of-record whose failure modes are harder to reason about, whose data has independent lifecycle from your application, and whose operation you now own end-to-end. Stateful complexity tends to be more expensive in the long run because state attracts more state, and ownership tends to be more expensive than people estimate at decision time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verdict shift.&lt;/strong&gt; Justified only if you actually need the session-control features that come with it (multi-IdP, fine-grained revocation, device tracking as a product feature). Otherwise, you've taken on durable architectural debt — and a permanent operational burden — to solve a hosting-cost problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Path 3: API Gateway Lambda authorizer reading cookies
&lt;/h2&gt;

&lt;p&gt;The cleanest path &lt;em&gt;if you control the gateway&lt;/em&gt;. Skip the BFF entirely. Configure the API Gateway with a custom Lambda authorizer that reads the auth credential from a cookie instead of the &lt;code&gt;Authorization&lt;/code&gt; header. Browsers send the cookie automatically on requests with &lt;code&gt;credentials: 'include'&lt;/code&gt;; the authorizer extracts and validates it; downstream services receive a Bearer token injected by the gateway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The shape:&lt;/strong&gt; HttpOnly cookie carries the Cognito JWT directly. The Lambda authorizer reads the cookie, validates the JWT against Cognito's JWKS endpoint (a library like &lt;a href="https://github.com/awslabs/aws-jwt-verify" rel="noopener noreferrer"&gt;&lt;code&gt;aws-jwt-verify&lt;/code&gt;&lt;/a&gt; handles the signature and claims validation cleanly), and tells the gateway to inject the token into the &lt;code&gt;Authorization&lt;/code&gt; header for the downstream call.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwikq2y7yvfazdx6gmim.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwikq2y7yvfazdx6gmim.png" alt="Path 3 — API Gateway Lambda Authorizer" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the architecture level, this is the most elegant of the four paths. No BFF. No session DB. No Vercel cost increase. Tokens never reach JS. Downstream services keep their existing JWT-from-header contract because the gateway re-injects it. Lambda authorizer responses are cached by API Gateway (default 300s), so the validation cost amortizes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it stops looking right — implementation level.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cookie size limits.&lt;/em&gt; Constraint #5 was waiting for this option. A full Cognito ID token plus an access token plus a refresh token can easily exceed the 4KB per-cookie browser limit. And on every request the browser sends, those cookies sit inside the total header size budget — most API Gateways cap around 8KB. Hit the cap, and the gateway returns HTTP 431 &lt;em&gt;before any of your code runs&lt;/em&gt;. This isn't a hypothetical; it's a documented production failure mode for Cognito users who try this naïvely.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Refresh token handling migrates into the auth infrastructure.&lt;/em&gt; This is the surface most underestimated at decision time. In the JS-readable token world, the auth library handles refresh transparently from the client: the client asks for a session, the library checks expiry, refreshes if needed, returns the token. The client never sees the mechanics. In this model, the client can't see expiration at all — and the authorizer's job is structurally "allow or deny," not "issue new credentials."&lt;/p&gt;

&lt;p&gt;So who refreshes? Three sub-options, each with cost:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;The authorizer itself,&lt;/em&gt; on every expired-token detection — but it then needs to write new cookies onto the response, which is awkward in an authorizer's lifecycle, and concurrent requests can stampede the refresh endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;A dedicated refresh route handler&lt;/em&gt; the client calls when it gets a 401 — this is the cleanest of the three, and the future state we ended up optimizing toward. It has well-defined seams, it's easy to test, and the client-side 401-then-refresh-then-retry pattern is a standard piece of HTTP plumbing when implemented carefully (with refresh deduplication so concurrent 401s don't trigger N parallel refreshes).&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Pre-emptive refresh from middleware&lt;/em&gt; — but middleware doesn't have a natural seam to mutate cookies on outbound responses in a way Next.js, the browser, and the gateway all agree on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these are blockers. All of them are real work. And refresh is the part of auth where bugs become production incidents fastest, because they manifest as intermittent 401s that are hard to reproduce.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;CSRF surface opens.&lt;/em&gt; When the credential travels in an &lt;code&gt;Authorization&lt;/code&gt; header set by your code, CSRF is structurally impossible — the attacker's page can't make the browser attach a custom header. When the credential travels in a cookie automatically attached by the browser, CSRF re-enters the threat model. You now need &lt;code&gt;SameSite=Lax&lt;/code&gt; (or &lt;code&gt;Strict&lt;/code&gt;), explicit anti-CSRF tokens for state-changing operations, or both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The non-technical reason this path didn't win — for us, this round.&lt;/strong&gt; Even with the refresh-route-handler model as the cleanest variant, we didn't pick Path 3, and the reason wasn't technical. The Lambda authorizer sat in another team's ownership, and that team had an active RBAC initiative consuming most of their bandwidth. Kicking off the cookie-authorizer rewrite at that moment would have meant either derailing their roadmap or eating cross-team coordination overhead that would have stalled both efforts. The right time for Path 3 was &lt;em&gt;after&lt;/em&gt; the RBAC work landed — which gave us a natural future state to optimize toward, rather than a path to force through now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Worth naming: architecture is org-shaped.&lt;/strong&gt; The "right" technical path is sometimes blocked not by technology but by ownership and timing — another team owns the relevant component, that team has competing priorities, kicking off a cross-team effort would derail their roadmap. That's not a failure mode; it's a constraint. Name it explicitly in the analysis, and shape today's decisions around the future state where the timing flips — rather than pretending the org-state is somebody else's problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verdict shift.&lt;/strong&gt; Cleanest of the active fix paths if downstream services and gateway are yours to modify &lt;em&gt;and&lt;/em&gt; the timing is right with the team that owns them. Costly enough in implementation work — particularly the refresh flow — that it should be entered into with eyes open, not signed up for at the elegant-diagram stage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Path 4: Conscious deferral + foundation work
&lt;/h2&gt;

&lt;p&gt;The "boring" option. Presented last because it only earns its place after the first three have lost some shine.&lt;/p&gt;

&lt;p&gt;Keep the current non-HttpOnly cookie storage. Mitigate the XSS surface via the usual hardening (strict CSP, short-lived access tokens, careful XSS posture in dependencies). Document the risk acceptance explicitly. Define what triggers the eventual migration. &lt;em&gt;Do the foundation work now&lt;/em&gt; that makes the eventual migration cheap when the trigger fires.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flgsqpo16fduna0ac4jg7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flgsqpo16fduna0ac4jg7.png" alt="Path 4 — Conscious Deferral with Foundation Work" width="799" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is not "do nothing." It's a substantial decision with substantial work attached.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the foundation work actually looked like:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Migrated from an older Amplify version that used self-hosted login pages — which structurally could not support HttpOnly cookies — to Amplify v6 with &lt;code&gt;ssr: true&lt;/code&gt; and Cognito Managed Login. That's the version whose experimental HttpOnly feature &lt;em&gt;exists&lt;/em&gt;. Moving to it converts the eventual migration from a six-month re-architecture into a config flag.&lt;/li&gt;
&lt;li&gt;Re-pointed the application's login UX from self-hosted pages to Cognito Managed Login, which is a prerequisite for Amplify's HttpOnly mode and also de-risks the future migration (no custom login UI to retrofit).&lt;/li&gt;
&lt;li&gt;Wrote an explicit risk acceptance — not a passing mention in a Slack thread, but a stakeholder-signed document describing the vulnerability we were knowingly keeping live, the mitigations in place, and the triggers that flip the decision.&lt;/li&gt;
&lt;li&gt;Defined the migration trigger. The primary trigger was the sunset of legacy frontend systems that were structurally incompatible with the new auth flow. Until those were gone, migrating the new system wouldn't actually have eliminated the vulnerability at the org level. A secondary trigger was a parallel RBAC initiative that would create a natural alignment point for backend/infra teams to revisit authentication anyway.&lt;/li&gt;
&lt;li&gt;Captured the full decision and option analysis — including the work that went into Paths 1-3 — so the next architect picking this up doesn't redo months of research.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The architectural appeal.&lt;/strong&gt; No disruption to a 100+ service system. Full understanding captured. The eventual fix is now &lt;em&gt;cheap&lt;/em&gt;, not &lt;em&gt;prohibitive&lt;/em&gt;. The decision is reviewable, with clear conditions under which it should be revisited.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the work that separates "ship the broken pattern" from "defer the fix with intent."&lt;/strong&gt; When the right answer is "don't change the externally-visible behavior yet," the work that earns that answer is invisible from the outside — but it's the work that determines whether the eventual change is a flag flip or a re-architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verdict.&lt;/strong&gt; In &lt;em&gt;this&lt;/em&gt; constraint stack, with these specific triggers visible in the roadmap, the right answer. Anchored explicitly: in a different stack (no Vercel, smaller backend, fewer downstream services, no upcoming roadmap alignment point), the verdict could land on any of Paths 1-3.&lt;/p&gt;




&lt;h2&gt;
  
  
  The decision matrix
&lt;/h2&gt;

&lt;p&gt;Compressing everything above into a comparison:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Frontend impact&lt;/th&gt;
&lt;th&gt;Backend impact&lt;/th&gt;
&lt;th&gt;Cost surface&lt;/th&gt;
&lt;th&gt;New attack surface&lt;/th&gt;
&lt;th&gt;Reversibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Path 1 — Next.js BFF&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High (all client API calls re-routed through Next.js)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Vercel compute doubles on proxied traffic&lt;/td&gt;
&lt;td&gt;CSRF if cookies auto-attached&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Path 2 — Broker + session DB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Low (gateway untouched)&lt;/td&gt;
&lt;td&gt;DB hot path; new infra cost&lt;/td&gt;
&lt;td&gt;CSRF + new failure mode&lt;/td&gt;
&lt;td&gt;Low (DB choice is sticky)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Path 3 — Gateway authorizer w/ cookies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Medium (refresh flow re-architecture)&lt;/td&gt;
&lt;td&gt;Medium (new Lambda authorizer + gateway config)&lt;/td&gt;
&lt;td&gt;Modest (Lambda invocations, amortized by cache)&lt;/td&gt;
&lt;td&gt;CSRF + cookie size risk + new refresh failure modes&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Path 4 — Defer + foundation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low (substrate upgrade)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Unchanged (deferred)&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The matrix shifts if specific constraints flip:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Not on Vercel?&lt;/em&gt; Path 1's cost surface mostly disappears. It becomes a strong default again.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Don't control the API Gateway?&lt;/em&gt; Path 3 evaporates.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Need session revocation as a product feature?&lt;/em&gt; Path 2 moves from over-engineered to required.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;No legacy frontend dependency?&lt;/em&gt; Path 4 loses its trigger and you go pick a real fix.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This kind of sensitivity is the point. The verdict isn't intrinsic to the path; it's intrinsic to the path &lt;em&gt;plus&lt;/em&gt; the constraint stack.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where architectural thinking ends and architectural judgment begins
&lt;/h2&gt;

&lt;p&gt;The meta-point of this article, explicitly:&lt;/p&gt;

&lt;p&gt;Architectural thinking, by itself, can absolutely tell you that Cognito tokens shouldn't be readable in JS. It can tell you that the broad shapes of the fix involve some combination of server-held state, BFF proxying, or gateway-level credential extraction. It can sketch you a clean diagram for each path and identify their structural trade-offs.&lt;/p&gt;

&lt;p&gt;Architectural thinking &lt;em&gt;alone&lt;/em&gt; cannot tell you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;That Vercel's billing model makes Path 1 expensive in a way that doesn't show up on the diagram.&lt;/li&gt;
&lt;li&gt;That Cognito tokens are too big to fit inside cookies the way Path 3 wants them to.&lt;/li&gt;
&lt;li&gt;That moving from one auth library version to another &lt;em&gt;is itself&lt;/em&gt; the substrate work that makes the eventual fix cheap.&lt;/li&gt;
&lt;li&gt;That vendor support (AWS Premium Support in our case) can give you two contrary answers if you ask twice — and that both can be correct under different assumptions.&lt;/li&gt;
&lt;li&gt;That your stakeholders can accept "we're deferring the fix" if you give them an artifact, instead of just giving them a meeting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These details don't live in the architecture diagrams. They live in implementation specifics, vendor docs, billing models, threat models, organizational state, and roadmap context. The job is to &lt;em&gt;go get them&lt;/em&gt; — read the vendor docs to the bottom, run the cost numbers, sketch the migration in enough detail that the unknowns become visible — and feed them back into the architectural choice.&lt;/p&gt;

&lt;p&gt;That's the thing worth leaving you with. &lt;strong&gt;Architecture is a discipline you do all the way down to implementation depth, or it's not architecture — it's a slide deck.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Acceptance of an existing flawed pattern can be a legitimate architectural outcome. So can adopting an experimental vendor feature, or building a new infrastructure component, or kicking the decision to the team that owns the gateway. What separates a good outcome from a bad one is whether the choice was made &lt;em&gt;with&lt;/em&gt; full visibility into its second- and third-order consequences, or &lt;em&gt;without&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;Surfaced throughout the article, collected here for reference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Map options against constraints, not features.&lt;/strong&gt; A pattern's quality is a function of context; the same pattern can be right or wrong in different stacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distinguish stateful complexity from feature complexity.&lt;/strong&gt; Both are complexity; they fail differently and accumulate differently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use foundation moves.&lt;/strong&gt; Modernize substrate now to make future fixes cheap. The work is invisible from outside but determines the cost of the eventual decision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ADR-as-artifact.&lt;/strong&gt; When you defer a decision, the deliverable is the documented decision and risk acceptance — not the absence of the change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture is org-shaped.&lt;/strong&gt; The "right" technical path is sometimes blocked by ownership and timing rather than technology. Name it explicitly in the analysis; design today's decision around the moment the timing flips.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vendor support is an input, not a conclusion.&lt;/strong&gt; Useful, often correct, never the last word. Ask twice; you'll get different answers when you clarify constraints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When deferring, write the trigger.&lt;/strong&gt; A deferral without a defined trigger is procrastination. With one, it's a roadmap entry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Walk implementation details for every option.&lt;/strong&gt; Without it, architecture is artificial in the best case, severely misleading in the worst.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;I wrote a companion piece on LinkedIn about the narrative side of this — what it felt like inside the team to spend weeks researching a security fix and then deliberately ship the pattern the pentest had flagged. [Link soon to come]&lt;/p&gt;

&lt;p&gt;The technical depth here is the substantiation. The thinking pattern — implementation-aware architecture — is the actual point.&lt;/p&gt;

&lt;p&gt;If your team is about to make an expensive-to-reverse architecture decision and wants an independent second pair of eyes, that's exactly the kind of work I run as part of architecture and cloud advisory engagements through Luckylabs. The analysis above is roughly the format of a typical engagement, applied to one specific problem. If it sounds useful, the fastest way to reach out is &lt;a href="mailto:dragos@dbln.me"&gt;dragos@dbln.me&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>security</category>
      <category>aws</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Sketching out the extremes: an approach to designing software architectures in highly unpredictable projects</title>
      <dc:creator>Bilaniuc Dragos</dc:creator>
      <pubDate>Mon, 12 Aug 2024 07:29:23 +0000</pubDate>
      <link>https://dev.to/dragosbln/sketching-out-the-extremes-an-approach-to-designing-software-architectures-in-highly-unpredictable-projects-1hd5</link>
      <guid>https://dev.to/dragosbln/sketching-out-the-extremes-an-approach-to-designing-software-architectures-in-highly-unpredictable-projects-1hd5</guid>
      <description>&lt;p&gt;Imagine a scenario: a fresh, ambitious project with enormous potential but limited resources. The stakes are high, and the product needs to hit the market as soon as possible to validate its potential and seize the opportunity. The roadmap is hazy, making flexibility crucial.&lt;/p&gt;

&lt;p&gt;Classic story until now. But here’s where things get spicy: the company that started the project has a huge community ready to jump on this new product they’ve been advertising for months. Thus, at the initial beta release, the system must be prepared to jump from 10 internal people testing it to anywhere from 20-100k daily active users and millions of events per hour.&lt;/p&gt;

&lt;p&gt;This mix of conditions creates a particular set of requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the system must be &lt;strong&gt;simple&lt;/strong&gt; enough to be handled by a few devs at the beginning, with short iteration time and cost-effectiveness being key&lt;/li&gt;
&lt;li&gt;it must be &lt;strong&gt;scalable&lt;/strong&gt; enough to handle the spike of users around the initial release date&lt;/li&gt;
&lt;li&gt;it must be &lt;strong&gt;flexible&lt;/strong&gt; enough to permit a rapid move toward scalability later on, delivering more and more complex features along the way&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The process
&lt;/h2&gt;

&lt;p&gt;The first step was to create an architecture that would satisfy all these requirements. &lt;/p&gt;

&lt;p&gt;As a preparation, I read and re-read the following books:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Fundamentals-Software-Architecture-Comprehensive-Characteristics/dp/1492043451" rel="noopener noreferrer"&gt;Fundamentals of Software Architecture: An Engineering Approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Building-Microservices-Sam-Newman-ebook/dp/B09B5L4NVT" rel="noopener noreferrer"&gt;Building Microservices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Designing-Data-Intensive-Applications-Reliable-Maintainable/dp/1449373321" rel="noopener noreferrer"&gt;Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drawing on the insights from these resources, along with my prior experience, I knew that some form of distributed architecture would be essential to handle the expected traffic.&lt;/p&gt;

&lt;p&gt;Roughly speaking, I followed these steps to arrive at an initial sketch of how the system would look like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Analyse requirements and &lt;strong&gt;gather events&lt;/strong&gt; that will need to be handled by the system&lt;/li&gt;
&lt;li&gt;Group those events into &lt;strong&gt;domain boundaries&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Identify &lt;strong&gt;architecture characteristics&lt;/strong&gt; (scalability, security, robustness - these kinds of things)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That initial sketch looked like this (in order to protect the intellectual property of the company, I anonymized all event and module names, keeping only the shape of the sketches):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhaht8zinlw81svb7nt2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhaht8zinlw81svb7nt2.png" alt="Diagram first version"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://drive.google.com/file/d/1tWDXhaaZA0qOCKnevK51Vf8-p38ZBVsf/view?usp=sharing" rel="noopener noreferrer"&gt;Readable version here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After lots of refinement and discussion sessions, two things became clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one big chunk of code (i.e a monolithic architecture) wouldn’t fit our scalability and flexibility needs&lt;/li&gt;
&lt;li&gt;a full-blown microservice architecture would be too complex and costly at this stage of the game&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, as with most things in life, the solution was somewhere in the middle. Finding that middle was now the challenge.&lt;/p&gt;

&lt;p&gt;Here’s where the approach that I’m proposing comes into play:&lt;/p&gt;

&lt;h2&gt;
  
  
  Sketching out the extremes
&lt;/h2&gt;

&lt;p&gt;Initially, the mindset was to design the simplest architecture that would satisfy our requirements and see if I noticed any specific areas of risk/improvement.&lt;/p&gt;

&lt;p&gt;The simplest architecture I could think of was a &lt;strong&gt;modular monolith&lt;/strong&gt;, where those modules would be as separated and clearly defined as possible. It looked something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64p6s1mbo9x6jrv1lt3z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64p6s1mbo9x6jrv1lt3z.png" alt="Architecture V1"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://drive.google.com/file/d/1CxW2T8DDMv0hw5KmKpHxwXbBdkySZx-P/view?usp=sharing" rel="noopener noreferrer"&gt;Readable version here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The thing that I thought would be the “secret sauce” here was the &lt;strong&gt;data access library&lt;/strong&gt;, a library shared between all modules, it would sit in front of the database layer and would be designed in such a way that extracting a module into its own microservice would take as little effort as possible, and we would only have to tamper with the shared library.&lt;/p&gt;

&lt;p&gt;As a bonus, and to be prepared “even more” for the move towards microservices, I was planning to deploy each module into its own independent function on the cloud infrastructure we were planning to use.&lt;/p&gt;

&lt;p&gt;After analyzing the approach a little more, two things became obvious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;implementing the “secret sauce” library in the way that I imagined wasn’t realistic, and it would lead to lots of complications&lt;/li&gt;
&lt;li&gt;deploying modules in different containers that accessed each other's databases risked creating a &lt;strong&gt;"Distributed Monolith"&lt;/strong&gt;—a problematic architecture that combines the worst aspects of monolithic and distributed systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, since I went to one extreme, i.e. the cheapest/fastest one, I thought it would be interesting to go to the other one as well: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What would the architecture look like, if we had all the resources we needed to create it?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After some more sketching, I arrived at this rough design of a microservice architecture for our system (I only highlighted some the inter-service events here):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3hw5rnewr4u0u939xdov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3hw5rnewr4u0u939xdov.png" alt="Architecture V2"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://drive.google.com/file/d/1CMwSF_n2WJBvUIt6QmJllG6QEn_bnKRX/view?usp=sharing" rel="noopener noreferrer"&gt;Readable version here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this version, we have some clear advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;individual scalability&lt;/strong&gt; of each module, based on loads&lt;/li&gt;
&lt;li&gt;clear &lt;strong&gt;ownership of the data&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;each module can be &lt;strong&gt;independently deployed&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, these advantages come at a cost: &lt;strong&gt;complexity&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Most of that complexity came from the inter-service communication. In V1 of the architecture, if module C needs data that is stored in database E, it can directly access it via the shared library. In this version, it has to request the data from Module C &lt;strong&gt;over the network&lt;/strong&gt; - which adds more points of failure and makes tracking and debugging more difficult.&lt;/p&gt;

&lt;p&gt;But even though this wasn’t the best solution for our current situation, it led us to some important insights based on which we built the actual architecture of the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;After taking a closer look, we noticed that most of the inter-service communication was happening between 3 of the 6 modules: Module C, Module D, and Module F. If the network communication between those services was somehow taken out of the picture, the remaining microservices would have a reasonable number of events and requests to share between them.&lt;/p&gt;

&lt;p&gt;So that is exactly what we did: compressed the 3 highly interrelated modules into a single modular microservice, and transformed the other modules into their own microservices. &lt;/p&gt;

&lt;p&gt;After some more tweaking and refining, this is the architecture we’ve come to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc0p31g752gfrw6hjgz7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc0p31g752gfrw6hjgz7.png" alt="Architecture V3"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://drive.google.com/file/d/1ReSScUSipffLwXTS13esrxdbPPiBmQYI/view?usp=sharing" rel="noopener noreferrer"&gt;Readable version here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are the advantages of this architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it retained the &lt;strong&gt;scalability advantages of microservices&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;the downsides of inter-service communication were reduced to a manageable level, enough so that our small initial team could &lt;strong&gt;implement the architecture in an efficient manner&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;the "big" microservice was &lt;strong&gt;implemented modularly&lt;/strong&gt;, allowing for future extraction of individual modules if needed&lt;/li&gt;
&lt;li&gt;the established microservice framework meant there would be &lt;strong&gt;less friction&lt;/strong&gt; when splitting additional components into new microservices&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Oftentimes, as software developers and architects, we are expected to come up with the ideal solution for any set of circumstances, requirements, or problems. We are aware, however, that everything in software development is a tradeoff.&lt;/p&gt;

&lt;p&gt;While this little story isn’t about promoting any specific type of software architecture, its purpose is to showcase a promising strategy for building software architectures, and it sounds like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;When trying to figure out where exactly to stop between two extremes, a good starting point is to sketch out how both of these extremes would look like.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In terms of software architecture, designing the cheapest and fastest architecture that would sort of satisfy the requirements, and putting it next to the most comprehensive and scalable solution can be very insightful. It can bring a better understanding of the system, its risks, and possibilities - as well as provide a clearer general direction for the product as a whole.&lt;/p&gt;

&lt;p&gt;In our case, this strategy showed us how a little tweak in the way we were organizing our components allowed us to aim much closer to the “ideal” microservice architecture than we had initially thought was possible. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;What insights would such an approach bring to your project and team?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>learning</category>
    </item>
    <item>
      <title>How I stopped freaking out when speaking to people | A journey with 4 lessons</title>
      <dc:creator>Bilaniuc Dragos</dc:creator>
      <pubDate>Fri, 23 Jul 2021 16:33:27 +0000</pubDate>
      <link>https://dev.to/dragosbln/how-i-stopped-freaking-out-when-speaking-to-people-a-journey-with-4-lessons-24jn</link>
      <guid>https://dev.to/dragosbln/how-i-stopped-freaking-out-when-speaking-to-people-a-journey-with-4-lessons-24jn</guid>
      <description>&lt;p&gt;Imagine: You're in 6th grade. Your English teacher gives you the main role in a poetry event that will appear on TV. On the big day, you walk on the stage. The camera turns upon you. Everyone's eyes turn upon you. You take a deep breath, and… blank.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IRDlaNEI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/he5jlp4i3jytpmhjwiwi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IRDlaNEI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/he5jlp4i3jytpmhjwiwi.jpg" alt="dark image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I always like to point to that story as the reason for my excessive fear of speaking in front of people. Of course, there must be lots of other reasons for it, but having a brain fart at 11 years old - on TV and in front of everyone - sounds dramatic enough, so we'll stick to that. The fact is, this became one of my deepest fears.&lt;/p&gt;

&lt;p&gt;Learning to live with this fear - and (spoiler alert) going from that panicked little kid to winning the Speaker of the Year award in front of over 300 people - was the most transformational journey of my life. It taught me some of the most important lessons I know, so I decided to write about them. Maybe they'll help you, too :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Denial
&lt;/h2&gt;

&lt;p&gt;For as long as I can remember, whenever I'd have to speak in front of people, my heart would start thumping, my mind would start racing and I'd start blurting out words rapidly and with no coherence. And the fact that &lt;em&gt;I was in complete denial of this fear&lt;/em&gt; didn't help at all.&lt;/p&gt;

&lt;p&gt;I quickly fell into a very nasty loop: I'd try to mask my insecurities with "confidence hacks" from youtube, people around me would smell that and become even more repulsed, which confirmed my insecurities, which in turn made me seek even more tricks and hacks… and so on.&lt;/p&gt;

&lt;p&gt;And this loop led me into a really dark place. I couldn't feel an authentic connection with anyone - not because there was anything wrong with the people around me, but because I never allowed them to see who I really was.&lt;/p&gt;

&lt;p&gt;All I was doing was keeping up this facade of fake confidence, and getting disappointed and frustrated every time it would inevitably fail to solve my problems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z5ORQUQZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9w24rstik8desxkoz9in.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z5ORQUQZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9w24rstik8desxkoz9in.jpg" alt="masks"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Change
&lt;/h2&gt;

&lt;p&gt;The trigger for change came at a leadership event that I participated in. I was my usual self, feeling awkward and trying to mask it with tricks and hacks.&lt;/p&gt;

&lt;p&gt;And then, there was this guy - speaking calmly, telling the right jokes at the right times, never really "trying" anything, but making everyone feel good - especially when he got in front of the group. Everyone wanted to be around him. And I wanted to &lt;em&gt;be him&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Following his advice, I joined Toastmasters, an organization that had regular meetings for practicing public speaking - and this is where the real pain of confronting my fears and insecurities began.&lt;/p&gt;

&lt;p&gt;At first, I was obsessively practicing my speeches (30–40–50 times!), just to make sure what happened in 6th grade would never happen again. And it went quite well, insofar as blocking on the stage went.&lt;/p&gt;

&lt;p&gt;But the painful part came after a speech was over, and I would look over the recording. I could barely stand to look for more than 2 minutes - that's how unnatural and awkward I saw myself on the stage. All my insecurities were exposed in front of everyone. And that was a hard pill to swallow.&lt;/p&gt;

&lt;p&gt;The only thing that kept me going was gradually learning the lessons I'll talk about. The made me stick to this journey, one painful step at a time, until I was holding this speech:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3-rij92I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o8gasmqx0r38ryqgygbp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3-rij92I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o8gasmqx0r38ryqgygbp.jpg" alt="speech"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;that ended up with me holding this beauty, as one of the biggest achievements of my life:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jBtcL3DP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tqypv5cfloppph74l5cy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jBtcL3DP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tqypv5cfloppph74l5cy.jpg" alt="award"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, on to the lessons…&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The most powerful thing to know is that it's okay to fuck up
&lt;/h2&gt;

&lt;p&gt;And I'm not saying it in a make-me-feel-better way. This is actually the best way to minimize the mental chatter that's such a big part of fear. &lt;/p&gt;

&lt;p&gt;Most times, fear would begin with the question "what happens if I fuck up?", which would trigger an endless loop of apocalyptic scenarios in my head - scenarios that were totally ungrounded in reality. Once I accepted that it's okay to fuck up, I could short-circuit the loop by answering that question with a realistic "nothing much".&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jEz0FJWt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8aqkvkvfexhmu3ke04dy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jEz0FJWt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8aqkvkvfexhmu3ke04dy.jpg" alt="shrug"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Toastmasters taught me that environment can play a crucial role here. If the feedback for my first speech was an honest "you suck, just go home" - you can bet I'd still be filling the pockets of "hack your confidence" gurus on youtube. &lt;/p&gt;

&lt;p&gt;Instead, the message was always: it's not a big deal - it happens to everyone. And that's about the most empowering message you can get when confronting fear and insecurities.&lt;/p&gt;

&lt;p&gt;Another thing that really helped me with this point was seeing other people around me awkwardly trying to confront the same fear and fucking up themselves. Knowing that I was not the only one struggling (and failing) was what kept me going, during some of my most intense moments of self-criticism. &lt;/p&gt;

&lt;p&gt;And this brings me to my second eye-opening lesson:&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Encouraging others is the best way of dealing with your own fear
&lt;/h2&gt;

&lt;p&gt;And this is something I  didn't expect at all: the most effective method of dealing with my own fear didn't have much to do with me. It was all about encouraging others to confront their own version of this fear of public speaking.&lt;/p&gt;

&lt;p&gt;And not just because it's the right thing to do in a higher, humanitarian way. It's actually the best thing you can do, egotistically speaking. Because when you see someone else dealing with the same kind of fear you're dealing with - and start encouraging them - something amazing happens:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;that fear becomes smaller for both of you&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This was another huge advantage at Toastmasters: being a member, I didn't only give speeches. I would also have to evaluate others, encourage them and give them the best feedback I was capable of. &lt;em&gt;And telling others that they can do it, I suddenly found myself believing it, too!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Find someone that's dealing with the same kind of fear. Encourage them and let them know that it's okay to struggle and even to fail. Then feel the empowerment this simple act brings upon you, in your own struggles.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o978qBju--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hrkb33mdtjbqy7oorjd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o978qBju--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hrkb33mdtjbqy7oorjd.jpg" alt="friends at the lake"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this lesson kept me fighting, until I finally realised that:&lt;/p&gt;

&lt;h2&gt;
  
  
  3. You don't conquer fear. You learn to live with it
&lt;/h2&gt;

&lt;p&gt;About 2 years passed since I won that trophy that marked the success of my "public speaking project". Since then, I've had quite a lot of events to moderate and speeches to present. In short, I kept gaining experience.&lt;/p&gt;

&lt;p&gt;But just the other day, I was going to this salsa&amp;amp;bachata party where I didn't know anyone. I arrived a little earlier, and there were a few people gathered up in a discussion. As I approached them, my heart started thumping, my thoughts started racing - all the good old friends were right back.&lt;/p&gt;

&lt;p&gt;And this is the biggest takeaway from my journey:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My fear never went away. I just learned to live with it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;More specifically, I learned to expect fear, &lt;em&gt;without expecting that it will ruin everything&lt;/em&gt;. To leave it in the background, and keep going anyways.&lt;/p&gt;

&lt;p&gt;I believe I learned to do this simply through experience. Speech after speech - no matter how much I rehearsed or how small the audience was - the same feelings of fear would arise. And, speech after speech, they would prove to be less tragic than I imagined.&lt;/p&gt;

&lt;p&gt;Eventually, those feelings became just part of the landscape - not going away, but not consuming all my attention, either. And that's how I started to actually enjoying public speaking. That's how my gruesome fight came to an end- not because I won or lost, but because &lt;em&gt;I stopped fighting.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;What I wish I knew then is how much mediation can help with this - since its core training is leaving thoughts and emotions in the background. And it's such an effective way of doing it that, in hindsight, I believe it would've saved me months of pain and frustration I had to go through, just to begin to learn this lesson.&lt;/p&gt;

&lt;p&gt;Just for the record, after trying out lots of apps and techniques, the most effective way of meditating for me right now is through &lt;a href="https://app.www.calm.com/program/mVcvqWcR8C/how-to-meditate"&gt;the guided sessions of Jeff Warren, available on Calm&lt;/a&gt;. If you have a hyperactive mind like mine, he might resonate with you, as well :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TrcDhcfQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f94vvlwtz0u8cvbfxnne.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TrcDhcfQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f94vvlwtz0u8cvbfxnne.jpg" alt="stones"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the last big lesson this journey had to teach me was that:&lt;/p&gt;

&lt;h2&gt;
  
  
  4. It's absolutely worth it
&lt;/h2&gt;

&lt;p&gt;I believe that one of the most perverse things when it comes to dealing with fear and insecurities is how easily the battle can be lost before it even begins.&lt;/p&gt;

&lt;p&gt;For such a long time, all I did was find circumstances and excuses. I'd tell myself it's alright, I'll eventually cover those insecurities up with confidence hacks. Or I'd have a little fuckup and see it as confirmation that I'll never be able to do it. Or, most often, I'd just delay things, expecting some enlightenment moment where all my fears and insecurities would disappear, just like magic.&lt;/p&gt;

&lt;p&gt;And now, I can confidently say that these were the worst ways in which I was sabotaging myself. Because learning to live with only this one fear, changed the way I looked at every other area of my life.&lt;/p&gt;

&lt;p&gt;More and more often, when faced with insecurities, fears and uncomfortable situations, I found myself thinking:&lt;br&gt;
 &lt;br&gt;
&lt;em&gt;"if public speaking didn't kill me, this won't kill me either"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And soon enough, this automatic way of thinking made me take on opportunities that would've terrified me before - opportunities that, among others, ended up sending my professional growth through the roof.&lt;/p&gt;

&lt;p&gt;I gained the courage to begin freelancing, to assume the role of Tech Lead in my projects, and, soon after, to become the CTO of a very promising startup.&lt;/p&gt;

&lt;p&gt;All of these moves came with lots of doubts, fears and insecurities packed in. And the only way I could get over them was through the lessons learned in this seemingly unrelated journey of confronting my deep fear of public speaking.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;So, that's about it for my journey. Confronting my fear taught me some of the most valuable lessons I know: that &lt;em&gt;it's okay to fuck up&lt;/em&gt;, that &lt;em&gt;encouraging others pays huge dividends&lt;/em&gt;, that &lt;em&gt;you can live with fear&lt;/em&gt; and that &lt;em&gt;it's totally worth doing it&lt;/em&gt;. I hope you found some value in those lessons, as well. &lt;/p&gt;

&lt;p&gt;But, at the end of the day, this is just one journey among millions. Fear and insecurities are everywhere, and each of us is trying our best to deal with them. If you're struggling, rest assured that you are not alone, not by a long shot. &lt;/p&gt;

&lt;p&gt;And if my specific lessons don't work for you, what will definitely work is what you're already doing now: keeping an open mind, seeking out new ideas and enlarging your own perspectives. A little bit from here, a little bit from there, and that's how you're building up your own recipe for dealing with this existential human condition.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Kudos to you, for keeping an open mind in front of so many fears and insecurities!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pe9CCXwN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/abxjoba9oerahvpl0p2a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pe9CCXwN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/abxjoba9oerahvpl0p2a.jpg" alt="smiling frog"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>motivation</category>
      <category>leadership</category>
      <category>learning</category>
    </item>
    <item>
      <title>I tracked every minute of my time for the last 4 months. Here are 7 totally unexpected results</title>
      <dc:creator>Bilaniuc Dragos</dc:creator>
      <pubDate>Wed, 14 Jul 2021 13:11:09 +0000</pubDate>
      <link>https://dev.to/dragosbln/i-tracked-every-minute-of-my-time-for-the-last-4-months-here-are-7-totally-unexpected-results-2dna</link>
      <guid>https://dev.to/dragosbln/i-tracked-every-minute-of-my-time-for-the-last-4-months-here-are-7-totally-unexpected-results-2dna</guid>
      <description>&lt;p&gt;A 30 minutes lunch break? Time entry. 12 minutes of arguing with mom? Time entry. 7 minutes of stalking my ex on Instagram? You guessed it!&lt;/p&gt;

&lt;p&gt;That was my life over the last 4 months, being my own time tracking cop while carrying out the most outrageous experiment of my life so far. The results amazed me in ways that I would never have expected, so I decided to write about them. Who knows, maybe you’re also going to find something of value in my journey.&lt;/p&gt;

&lt;p&gt;But first…&lt;/p&gt;

&lt;h1&gt;
  
  
  What the hell made me do it?
&lt;/h1&gt;

&lt;p&gt;To be honest, it was a combination of frustration, guilt and fear — all generated by the fact that I kept setting big goals for myself, but never seemed to make any progress towards them. Time was passing, and I had nothing to show for it.&lt;/p&gt;

&lt;p&gt;All I had were vague reports at work, where “working” covered everything from writing code, to talking to people, to watching Russian slapping contests on youtube. &lt;/p&gt;

&lt;p&gt;I knew I had to do start tracking my time if I wanted to keep my sanity. And I’ve seen how something casual/half-hearted would quickly become too vague to be of any use. If I wanted to do it, I had to go all-in.&lt;/p&gt;

&lt;p&gt;So…&lt;/p&gt;

&lt;h1&gt;
  
  
  How exactly did I do it?
&lt;/h1&gt;

&lt;p&gt;I used an app called Toggl to do all my tracking. I chose this specific app because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it’s available on all platforms and syncs very nicely between them&lt;/li&gt;
&lt;li&gt;it has an intuitive UI, with suggestions that become more and more accurate over time&lt;/li&gt;
&lt;li&gt;it allows for very fine customization and reporting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first, I devised 7 main areas where all my entries would fall, using tags and colors to mark them in the app:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1whxgy6oalqmzo09yjjo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1whxgy6oalqmzo09yjjo.png" alt="areas"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, I created some high-level projects that I knew I was already spending time on:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmvgtnv0grk1n7x4rolj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmvgtnv0grk1n7x4rolj.png" alt="projects"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the setup was done, I would simply start a new time entry, every time I would move from one activity to the other.&lt;/p&gt;

&lt;p&gt;One important note here was that, because I decided to go all-in, I had to be particularly careful not to have any entries “cover up” unrelated things that I was doing. For example, if I would be writing code on my project and I’d receive a call, I’d have to create a separate time entry for it, even if it only took 5 minutes.&lt;/p&gt;

&lt;p&gt;This level of strictness was a bit taxing at the beginning, but after a while, Toggl’s UI came in very handy. I rarely had to create new entries. Most of the times when I’d switch to something else (even just short interruptions), I would just have to press “continue” on a previous entry.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fed886sh38nmdoryvk4or.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fed886sh38nmdoryvk4or.png" alt="continue"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the end of the week, here’s how my timetable would look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw2hb3mi44c4z062mlafa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw2hb3mi44c4z062mlafa.png" alt="timetable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now that the “how” is also out of the way, let’s move on to the exciting stuff. Here are the biggest changes I noticed, over these 4 months:&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Drastically improved my focus and productivity
&lt;/h1&gt;

&lt;p&gt;Yep, the biggest impact of this time tracking journey didn’t come in the form of a mind-blowing insight at the end of the week, when I was looking over my timetable. The biggest impact was in how I was spending my time &lt;em&gt;while I was doing the tracking.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At first, nothing big happened. But after a while, I found myself more and more often in an interesting situation. Whenever I was working and felt the need to “zone out” by jumping “just a bit” on youtube or Instagram, I’d find myself thinking “nah, I don’t want to start a new entry now. I’ll just get this thing done, and then take a bigger break for that”.&lt;/p&gt;

&lt;p&gt;And, more often than not, I wouldn’t even feel that need for youtube or Instagram anymore, once I actually finished the task. The feeling of accomplishment was enough to give me the refreshment I needed.&lt;/p&gt;

&lt;p&gt;This increase in focus sent my productivity through the roof. Yes, I’ve always read and heard of how context switching is a very bad idea. But, until I tracked it down, I never knew how often I was doing it — and I never knew that getting rid of it would make me get things done literally twice as fast! After seeing all this for myself, I felt like I somehow hacked my own life.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Saved a lot of time from unexpected places
&lt;/h1&gt;

&lt;p&gt;One of the most shocking insights that I had in the beginning, after looking at my reports for a week, was that I was spending over 20 hours a week on food-related activities (buying food, cooking, eating).&lt;/p&gt;

&lt;p&gt;Every day, 3 times a day, I would take some time off to cook. And, since eating healthy was always an important thing for me, I didn’t feel bad if it sometimes took a little longer. But I never knew I was doing the work of a part-time cook out there! At least if I’d learned to cook something more exciting than this boring salad:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fih3ep2rs57plb0ii97h1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fih3ep2rs57plb0ii97h1.jpg" alt="salad"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once I became aware of this, I automatically started thinking about how I could make it a bit more efficient. A simple thing that popped into mind was that, instead of cooking everything from scratch in each of the 3 breaks, I could simply prepare everything in the evening before, and have my food ready to go for the next day, with minimum adjustments.&lt;/p&gt;

&lt;p&gt;This trick solved all my cooking for the day in under 1 hour, instead of 2–3, which amounted to over 10 hours of saved time, per week. And the best part was that I didn’t have to sacrifice anything in terms of how healthy or tasty my food was!&lt;/p&gt;

&lt;p&gt;Such a simple solution. However, I would never have thought of it, if there wasn’t this table that was telling me straight to my face: “here’s how much time you’re actually spending on this thing”.&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Formed habits &amp;amp; routines much easier
&lt;/h1&gt;

&lt;p&gt;Turns out time tracking helped with my habits and routines, as well, in two not-so-obvious ways:&lt;/p&gt;

&lt;p&gt;1 - If I would have the same entries at roughly the same hours, Toggl’s mobile app would start suggesting them, in those time intervals. This made my tracking way easier, and turned the clock into a kind of trigger for the habits I was trying to form:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4xypkxk53w0xmoflige.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4xypkxk53w0xmoflige.png" alt="suggestions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 - There was a deep satisfaction when I would look at my weekly timetable and see all the entries nicely aligned. Here’s one of the weeks that I’m most proud of. Just look at how satisfying those morning entries look:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qh2d9wt03fpeuiqtl2h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qh2d9wt03fpeuiqtl2h.png" alt="habits"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It might sound trivial, but just these two simple tricks were enough to make me form and cement very helpful habits, without thinking too much about them.&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Enjoyed my “chill time” more than ever
&lt;/h1&gt;

&lt;p&gt;Here’s something interesting. This experiment, which was chiefly meant to increase my productivity, had another very unexpected — but very welcomed — effect: it increased the quality of my “chill time”, as well!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8h66gso3imtvopke017p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8h66gso3imtvopke017p.jpg" alt="chill"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Firstly, as I was doing my work much more efficiently and saving time from all kinds of unexpected places, I found myself with more and bigger blocks of time on my hands. That meant I could fit in some leisure activities that were more time-consuming — but that I really enjoyed doing.&lt;/p&gt;

&lt;p&gt;Secondly, all this increased amount of “chill time” came without the usual guilt I felt before, when I was “chilling” by scrolling through the Instagram feed, while I knew I had to fix that stupid programming bug at work.&lt;/p&gt;

&lt;p&gt;This made me enjoy my free time like never before, and rekindle old passions like salsa &amp;amp; bachata —passions that I forgot how good they made me feel, amongst all this clutter of work and guilt and continuous distractions.&lt;/p&gt;

&lt;h1&gt;
  
  
  5. Made better decisions, overall
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F550qasv72f2vac0cs6w1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F550qasv72f2vac0cs6w1.jpg" alt="choices"&gt;&lt;/a&gt;&lt;em&gt;one of the toughest decisions in life&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Since I was being as honest as I could with those time entries, weighing my decisions wasn’t that complicated anymore: I would look over my timetable, see exactly how much time I spent on something I decided to do, and look at how much I got out of it.&lt;/p&gt;

&lt;p&gt;This way, “Is it a good idea to write that article for my 23rd birthday?” became “Is it a good idea to write that article for my 23rd birthday, given the fact that last week I spent 11 hours, and got nowhere with it?”. Not so hard to see the issue, from that perspective.&lt;/p&gt;

&lt;p&gt;As a bonus, tracking my time solved another one of the biggest problems I had, in terms of decision making. I always had the tendency to overestimate my abilities and take on much more than I could actually handle. This obviously had some very bad consequences, like frustrating other people that were working with me.&lt;/p&gt;

&lt;p&gt;Well, once I had this sheet that was telling me “this is how much it actually takes you to do it” and “this is how much free time you have on your hands right now”, deciding whether I could or could not handle something new became a factual decision, rather than a whim of my arrogant ego.&lt;/p&gt;

&lt;h1&gt;
  
  
  6. I finally felt in control of my time
&lt;/h1&gt;

&lt;p&gt;As I said in the beginning, the irreversible passing of time was one of the biggest sources of stress and anxiety for me. And, while I’m still having my fair share of existential crises about it, doing this experiment drastically reduced that stress and anxiety. The main reason was that, again,&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I finally felt in control of my time.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yes, I was still binge-watching cat videos on youtube, probably more than I should. But at least it was a conscious decision, rather than a reaction to some algorithms designed by smart people to make me mindlessly spend hours on end on their website. And this “conscious decision” part was what made all the difference, for me.&lt;/p&gt;

&lt;p&gt;And the coolest thing was that I didn’t have to change anything in the way I was spending my time, in order to feel better about it. Simply having it noted down was enough to give me that empowering feeling of control.&lt;/p&gt;

&lt;h1&gt;
  
  
  7. Felt more tense, uneasy and guilty (at first)
&lt;/h1&gt;

&lt;p&gt;Surprise-surprise: this is not a silver bullet to shoot down all of life’s problems. It actually came with some not-so-nice consequences that I have to mention, if I am to paint an honest picture of my journey.&lt;/p&gt;

&lt;p&gt;First up, I became more tensed and uneasy, especially in the beginning. I think that’s not too unexpected — just imagine having a cop on your back, 24/7, that sees every single thing your doing, and tracks it down on a sheet that’s gonna stare you in the face every Sunday. Quite a reason to feel uneasy…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbc514o3pa2fk2i8xcrxt.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbc514o3pa2fk2i8xcrxt.jpeg" alt="police"&gt;&lt;/a&gt;&lt;em&gt;shoutout to Mr. policeman, for not arresting me when I randomly asked him to pose for my blog&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The other thing was guilt. Again, especially in the beginning. After the first few weeks, I was confronted with a hard truth: I was wasting time. Lots of it. And not in a vague way. I could actually count the hours I spent on things that were totally unproductive, projects that failed and times when I did something completely different than what I had to. Talk about pills that are hard to swallow…&lt;/p&gt;

&lt;p&gt;I eventually managed to keep those bad sides under control through other habits, like meditation. That being said, this journey was definitely not all fun and rainbows.&lt;/p&gt;




&lt;p&gt;So, that’s about it for my journey. Currently, I got so used to this system and it seems to work so well for me, that I’m gonna keep doing it — as long as I’ll be able to keep those negative sides under control.&lt;/p&gt;

&lt;h1&gt;
  
  
  Afterthought: it’s not as hard as it seems
&lt;/h1&gt;

&lt;p&gt;I’ve been showing this article to some friends, to get some feedback before publishing it. A common response was: “Wow, that’s so impressive! You must be so disciplined! I could never do that.” And while it tickled my ego to hear this, the truth is, it’s really not that hard.&lt;/p&gt;

&lt;p&gt;Yes, like all things, it requires effort in the beginning. But after you got it all set up and run it for a few days, it becomes pretty easy. 99% of the time, you’ll just press “continue” on a previous entry, which only takes 5 seconds. And since you’ll have to do it dozens of times a day, it will become instinctive much sooner than the usual “3–8 weeks to form a new habit”.&lt;/p&gt;

&lt;p&gt;Even now, my timer runs “Blog — time tracking” for 9 minutes and 20 seconds. I don’t remember having made a conscious decision to start it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tips &amp;amp; tricks
&lt;/h1&gt;

&lt;p&gt;If you like the idea and consider trying it for yourself, here are some things I wish I knew when I started, and that I hope will help you in your journey:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Try to be as honest as possible&lt;/strong&gt;. The benefits are gone if you find yourself scrolling through your Instagram feed, while your timer says “preparing yearly report”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep it personal.&lt;/strong&gt; Don’t mix it up with any tracking software from work. Don’t tell anyone about it. Basically, don’t do anything that would make you feel even remotely uncomfortable about recording those 2 hours of binge-watching Japanese eating contests on youtube.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frq6hgm2b4lwugw5nqfqk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frq6hgm2b4lwugw5nqfqk.jpg" alt="private"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep it simple. As simple as possible.&lt;/strong&gt; Don’t overkill it with tags and projects (the way I did, in the beginning). You can always add those later. The whole system should be a pleasure to use, or you’ll have trouble using it at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One step at a time.&lt;/strong&gt; At first, don’t change anything in how you spend your time. Just get used to tracking down what you’re already doing. The main focus is to get used to pressing “play” every time you’re doing something new.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be patient with yourself.&lt;/strong&gt; Once you start doing this in full honesty, you’ll probably see that your time isn’t really spent the way you imagined. That’s an easy way for guilt to creep in. But don’t despair. Once you become aware of this, things will get better by themselves. And keep in mind that, just by trying it out, you’ve already done something very courageous that’s a huge achievement in and of itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Tracking every minute of my time is, by far, the most effective thing I’ve ever tried, in terms of becoming more focused, getting more done and improving the quality of my time.&lt;/p&gt;

&lt;p&gt;But, at the end of the day, this is just another way in which someone on this planet is trying to deal with the fact that life is hard. And if my trick doesn’t work for you, what will definitely work is keeping this healthy mindset that makes you read these kinds of articles, in the first place. Kudos to you, for keeping an open mind in the face of life’s hardships!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We’re all trying to make the most out of our time. Thank you for spending some of yours with me, today!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vvoxex6a5xbfyjg3kz7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vvoxex6a5xbfyjg3kz7.jpg" alt="light"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PS: This is the first article I’ve ever written, so I think you can imagine how anxious I am about it 😬 Any though (positive or constructive), clap, comment, share, or feedback in any form would be very, very much appreciated!&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>motivation</category>
    </item>
  </channel>
</rss>
