<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Sunny</title>
 <link href="/atom.xml" rel="self"/>
 <link href="https://twkrr.com/"/>
 <updated>2026-01-23T22:20:48-06:00</updated>
 <id>https://twkrr.com</id>
 <author>
   <name></name>
   <email></email>
 </author>

 
 <entry>
   <title>Path to self-driving software</title>
   
      <link href="https://twkrr.com/2026/01/24/path-to-self-driving-software/"/>
   
   <updated>2026-01-24T00:00:00-06:00</updated>
   <id>https://twkrr.com/2026/01/24/path-to-self-driving-software</id>
   <content type="html">&lt;p&gt;I came back from holiday and every engineer I follow on Twitter was using coding agents. Claude Code, Codex, Gemini, all of them getting better. I’d been using AI in code editors, but not in an agentic way. This time I gave it a proper go.&lt;/p&gt;

&lt;p&gt;We had a bunch of bugs to clear before starting the year fresh. Small fixes, contained changes. I pointed an agent at them and let it run.&lt;/p&gt;

&lt;p&gt;It worked surprisingly well. The agent would read files, write code, run tests, loop when something broke. It just kept going until the problem was solved.&lt;/p&gt;

&lt;p&gt;But when I tried to go further, I hit friction. I’d imagine many others did too.&lt;/p&gt;

&lt;p&gt;Most of our code wasn’t written yesterday. It carries context that lives in people’s heads. Local dev looks different from staging, staging looks different from prod. Even amongst humans, there’s no standard way of doing things. And all my life as an engineer, I’ve worked on one thing at a time. Take a task, write the code, open a PR. That’s the rhythm.&lt;/p&gt;

&lt;p&gt;AI agents make parallelisation possible. Not for complex work, but for the simpler stuff. But when the agent writes code, how do I know it’s right? How do I check on what it’s doing without waiting until the end? The terminal scrolls by. I can’t parse it. I don’t want to stop it, but I don’t trust it either.&lt;/p&gt;

&lt;p&gt;What I wanted was to verify the work the way I’ve always verified work. Open it in my editor. Read the code. See the diff. Use the tools I already know.&lt;/p&gt;

&lt;p&gt;That’s the gap I started thinking about.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;adoption-becomes-autonomy&quot;&gt;Adoption becomes autonomy&lt;/h3&gt;

&lt;p&gt;The transition to AI isn’t a flip. It’s not about replacing everything overnight.&lt;/p&gt;

&lt;p&gt;It’s humans and agents working together, gradually building toward autonomy. The more you work with agents, the more context you generate. The more context they have, the more they can do.&lt;/p&gt;

&lt;p&gt;I wasn’t looking at what others are doing with AI and trying to copy it. I was thinking about how to bring agents into the workflows we already have.&lt;/p&gt;

&lt;p&gt;It should feel familiar. Same git, same editor, same workflow. When you take over from an agent, you’re working the way you always have.&lt;/p&gt;

&lt;p&gt;It should enable parallelisation. This is a real shift in how you operate. Humans take one task at a time. But with isolated workspaces, you can spin up multiple agents on different tasks, check back when ready, review and merge what works. It takes time to get comfortable with. But it’s how leverage actually scales.&lt;/p&gt;

&lt;p&gt;Eventually, with strong enough verification (tests, deploys, rollbacks), software starts driving itself. But you don’t get there by rewriting everything. You get there by working together.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;an-environment-for-humans-and-agents&quot;&gt;An environment for humans and agents&lt;/h3&gt;

&lt;p&gt;Agents should work the way you already work. Same tools, same patterns. Environments you control. The ability to check in whenever you need to.&lt;/p&gt;

&lt;p&gt;You already branch for features. You already isolate work so it doesn’t conflict. A workspace for agents is that same pattern: a branch, a set of repos, everything kept separate from your other work. You can have many running at the same time.&lt;/p&gt;

&lt;p&gt;You already run things in containers. An agent can run in one too, with full permissions inside, isolated from your system. It can install packages, run commands, do whatever it needs. When you want to check on its work, you open the same files in your editor.&lt;/p&gt;

&lt;p&gt;You already spin up Postgres, Redis, whatever the app needs. Agents need the same. They should be able to run tests against real services, not mocks. The environment should feel like yours because it is yours.&lt;/p&gt;

&lt;p&gt;The handoff is what matters most. One command opens the workspace in your editor. Same files, same git history, same workflow. You verify the work using tools you already know.&lt;/p&gt;

&lt;p&gt;The agent works in your world, not some parallel universe you need to translate from.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;self-driving-software&quot;&gt;Self-driving software&lt;/h3&gt;

&lt;p&gt;You start writing things down that you never bothered to document before. Agent docs, notes on how things connect, context that used to live only in your head. Now something else needs to understand your codebase, and that something is actually reading what you write.&lt;/p&gt;

&lt;p&gt;The agents get better at your codebase specifically. They pick up your conventions, your preferences, the way you structure things. Knowledge that used to live in one person’s head starts living in the system.&lt;/p&gt;

&lt;p&gt;This is the flywheel. Adoption generates context. Context improves capability. Capability makes adoption easier. Teams that start accumulating this context now will have compounding advantages later.&lt;/p&gt;

&lt;p&gt;That’s the bet. Not rewriting everything for AI, but working together and building up context over time.&lt;/p&gt;

&lt;p&gt;I took a bunch of Waymo rides last year. It’s a car. I could see the road, the steering wheel turning, the world outside. Familiar, but also kind of magical.&lt;/p&gt;

&lt;p&gt;Self-driving software should feel the same. Same git, same editor, same workflow. You can open the workspace, see the code, understand what changed. Familiar, but the work moves forward on its own.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AI is at the PageRank moment</title>
   
      <link href="https://twkrr.com/2025/08/23/ai-pagerank/"/>
   
   <updated>2025-08-23T00:00:00-05:00</updated>
   <id>https://twkrr.com/2025/08/23/ai-pagerank</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;History doesn’t repeat itself, but it often rhymes&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I was a year‑old kid when the internet was happening, so most of my context here is from reading and intuition. But the patterns feel familiar enough to be worth calling out.
When Google won search, it wasn’t because they had the only algorithm. For a while, everyone had one: Altavista, Yahoo. They were all good enough, and eventually they all started looking the same.&lt;/p&gt;

&lt;p&gt;Google’s edge wasn’t just PageRank. In many ways, PageRank was the first clear milestone, not the first search algorithm, but the one that scaled effectively, showed the system really worked, became the common standard, and then drove value once paired with the right distribution and business model. It was distribution (default in browsers), monetisation (AdWords), and a product flywheel that made the experience sticky.&lt;/p&gt;

&lt;p&gt;The “search wars” ended after that and what followed was the real unlock: the information economy, digital marketing, ecommerce, and entire industries built on top of stable infrastructure.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;the-convergence&quot;&gt;The convergence&lt;/h3&gt;
&lt;p&gt;GPT‑5, Claude 4.1, Gemini 2.5, and Grok 4 all shipped in mid‑2025. Across providers, the patterns are increasingly similar: tool use/function calling, long contexts, retrieval/caching, structured outputs, and in some cases explicit routing between fast and deeper‑reasoning modes or multi‑agent variants (for example, Grok 4 Heavy). That convergence makes it feel like we’re only months away from frontier models that are close in day‑to‑day capability for most work.&lt;/p&gt;

&lt;p&gt;Public leaderboards and evaluation round‑ups show small margins between the top models rather than runaway winners. Pricing bands are also narrowing: consumer chat tiers cluster in the same range (with new low‑cost plans in some regions), and API pricing is trending down via cheaper SKUs and features like caching and batching.&lt;/p&gt;

&lt;p&gt;Meanwhile, the current way of scaling models appears to deliver diminishing returns. Training and infrastructure costs are huge, the model’s half‑life is short as competitors ship upgrades, and most labs are still pushing the same transformer recipe, making it hard to build a durable moat or justify relentless reinvestment.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;everything-becomes-a-commodity&quot;&gt;Everything becomes a commodity&lt;/h3&gt;
&lt;p&gt;These research labs are already on a path to becoming infrastructure companies, something like “AWS for intelligence”. The APIs and features they now ship look less like experiments and more like standardised building blocks that any developer can plug into. This is what makes them feel like a commodity layer in the making.&lt;/p&gt;

&lt;p&gt;Look at OpenAI’s API surface: file uploads, vector store access, structured responses, evals, tracing. It reads less like a “chatbot product” and more like AWS for intelligence. The primitives are being standardised for developers, not just end users. And it’s not just OpenAI. Anthropic, Google, xAI, Cohere, and Mistral are all exposing nearly identical primitives — tracing, evals, long contexts, caching, structured outputs, and tool use. Everyone is converging on the same infra surface.&lt;/p&gt;

&lt;p&gt;When the product looks the same and the price is the same, the moat shifts to:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Who owns the rails (infra, APIs, data centres, developer platforms)&lt;/li&gt;
  &lt;li&gt;Who owns the users (700m ChatGPT users, Microsoft’s enterprise channels, Google defaults, Elon’s X)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how commoditisation typically happens: once differentiation narrows, offerings look alike, pricing compresses, and competition shifts to who controls scale, rails, and distribution. It doesn’t happen overnight, but the trend is clear.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;companies-are-finding-their-positions-in-the-market&quot;&gt;Companies are finding their positions in the market&lt;/h3&gt;

&lt;p&gt;We used to carry doubts about AI. But the trajectory over the past few years is clearly different. People are searching more and asking longer, more complex questions; Google’s AI Overviews are actually showing more links, surfacing more websites, and driving higher‑quality clicks. ChatGPT, meanwhile, is becoming a discovery engine in its own right, guiding users to new products, services, and content. Other real use cases are surfacing: shoppers using AI to compare products across sites, travellers planning trips through conversational agents, students and researchers drafting work with copilots, and businesses integrating AI to triage support tickets or generate code. Enterprises are embedding copilots directly into workflows from Office to Salesforce to Google Workspace, which drives daily use.&lt;/p&gt;

&lt;p&gt;What’s different now is that companies aren’t just experimenting but are staking positions. Consumer apps like ChatGPT have reached hundreds of millions of users. Enterprise copilots are embedded across core productivity suites. Infrastructure providers resemble utilities, with APIs standardising across OpenAI, Anthropic, Cohere, Google, and others. Large incumbents are locking in distribution and partnerships — Microsoft with OpenAI, Amazon with Anthropic, Google with its own models.
Categories are firming up, leaders are visible, and consolidation is underway.&lt;/p&gt;

&lt;p&gt;The market is no longer asking who has the smartest model; it’s who secures the strongest position before the window closes.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;The near‑term feels familiar: convergence, commoditisation, distribution wars. The playbook is recognisable, much like the end of the search wars after PageRank proved itself narrow differentiation at the model level, competition shifting to rails and distribution, and consolidation among a few large players. It’s the same rhythm: once the underlying models converge, the contest moves to scale and channels.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>What I&apos;m working on (2025)</title>
   
      <link href="https://twkrr.com/2025/06/06/atlas-update/"/>
   
   <updated>2025-06-06T00:00:00-05:00</updated>
   <id>https://twkrr.com/2025/06/06/atlas-update</id>
   <content type="html">&lt;p&gt;It feels like the right moment to write this.&lt;/p&gt;

&lt;p&gt;Atlas marked another anniversary of the moment things became real: processing our first order. It feels like a good time to pause, reflect on what we believed, see how the world has shifted, and how our assumptions have evolved.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;where-is-atlas-now&quot;&gt;Where is Atlas now&lt;/h3&gt;

&lt;p&gt;Singapore is still home, and where most of our customers operate.&lt;/p&gt;

&lt;p&gt;Every day, hundreds of restaurants rely on Atlas. We help them make hundreds of millions of dollars annually, generating millions in revenue for ourselves. Some of the most loved brands—Killiney, Haidilao, SaladStop, Les Amis Group—run on us today. A few personal favourites are in the mix too: PPP Coffee, Huevos—happy places I keep finding reasons to ‘check in on.’ And we continue to onboard new restaurants every single week.&lt;/p&gt;

&lt;p&gt;Restaurants now use Atlas to manage everything: online ordering, point-of-sale, QR code ordering, kiosks, aggregating orders from all food delivery platforms, loyalty, and a growing set of AI tools. Internally, we joke that we have more products than engineers. Everything runs 24/7—it kicks off with an 8am coffee at CSHH, one of my favourite spots (and a morning coffee institution), and wraps up past 3am at Backdrop, where Dario’s team is slinging proper cocktails. In between, at spots like Willow—a Michelin-starred restaurant—the staff deliver world-class service, customers place orders around the clock from across the country, and Atlas quietly keeps everything moving in the background.&lt;/p&gt;

&lt;p&gt;The team is still lean and mean. We recently welcomed another engineer, we’re still looking for a truly world-class designer (our CPO covers design for now). Sales and support have expanded, and we’ve got a hobby entrepreneur-in-residence helping build a great community of restaurant operators.&lt;/p&gt;

&lt;p&gt;We’re profitable, steadily growing, and focused on building something our customers—and we ourselves—genuinely love. Each day is an adventure, and the ambition to create world-class infrastructure that’s reliable,	 invisible, and built to last is what keeps us going.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;what-we-are-learning&quot;&gt;What we are learning&lt;/h3&gt;

&lt;p&gt;Singapore’s restaurant scene is vibrant and brutal. Over 10,000 restaurants make 12 billion dollars each year. In 2024, 3,791 opened and 3,047 closed — the highest count in almost two decades. Running a restaurant is tough.&lt;/p&gt;

&lt;p&gt;Diners are returning to restaurants, but with new expectations. They now move fluidly between online ordering, dining in, and delivery. Loyalty and consistent experiences across these channels are increasingly important to them.&lt;/p&gt;

&lt;p&gt;Restaurants are adapting to keep up with how diners now behave, even as they manage rising manpower costs and maintain good service. Dine-in places are adding online ordering and delivery, while online-first brands are figuring out whether to stick with legacy POS systems or experiment with something new. In short, restaurants want tools that just work—loyalty, ordering, POS, delivery—all integrated smoothly, without extra headaches.&lt;/p&gt;

&lt;p&gt;Restaurant closures are always a risk, but even with them rising, we see resilience in four types. First, long-standing institutions are updating their systems to stay relevant and adapt to changing customer behaviors. Second, independent restaurants are finding breakout niches or dishes and strategically scaling them to millions. Third, larger groups continue acquiring and consolidating various brands under one roof. Fourth, new formats experiment by launching fresh concepts to existing customer pools, then rapidly scale successful ones.&lt;/p&gt;

&lt;p&gt;Restaurants are moving quickly. We’re building tools to transform them.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;what-im-working-on&quot;&gt;What I’m working on&lt;/h3&gt;

&lt;p&gt;Restaurant operators aren’t engineers. They don’t care about our architecture or tech-stack choices. They care that orders go through, payments land, and things run smoothly, even on their busiest days. Internally, this perspective has turned into a bit of a running joke: ‘but merchants don’t care.’ (I’ve even made some memes about it)&lt;/p&gt;

&lt;p&gt;As Atlas grows, we’re supporting more restaurants, processing more transactions, and facing more ways things could break—with more people counting on us to get it right. Speed and scale clarify things quickly: how fast we move shows how clearly we’re thinking, how well we’re executing, and how ready we truly are.&lt;/p&gt;

&lt;p&gt;When I talk about scale, I mean something simple and specific: It has to work. At any hour, in any setup, at any volume.&lt;/p&gt;

&lt;p&gt;Over the past few months, I’ve spent more time making sure our foundations are solid enough to reliably handle 3x, 5x, and eventually even 10x our current volume. Most of this meant thinking ahead, simplifying wherever we could, and staying disciplined in how we built, tested, and shipped. It involved placing some wild bets, talking to people who’ve built at scale, borrowing best ideas, carefully migrating systems, and steadily raising our own bar.&lt;/p&gt;

&lt;p&gt;We’ve rewritten the entire infrastructure multiple times and improved the way we build, test, release, observe, and recover when things go wrong.&lt;/p&gt;

&lt;p&gt;Here are a few engineering highlights (I spend most of my time here):&lt;/p&gt;

&lt;h4 id=&quot;infrastructure&quot;&gt;Infrastructure&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;We migrated away from a serverless infrastructure that served us well in the early days to a Kubernetes setup that fits our model of isolated compute far better. It unlocked effectively unlimited scale on compute while keeping costs manageable (by resharing the same resources with different utilisation limits for different types of restaurants). It gave us first-class support for database-backed background jobs—critical for time-sensitive operations—and let us easily spin up new workflows that fit our setup, almost like we are building our own platform as a service tool.&lt;/li&gt;
  &lt;li&gt;Scaling databases has been one of our toughest challenges. We offer tenant isolation on a shared database, making it tricky to manage resources and connections. By tuning databases, optimizing queries (repeatedly!) to reduce CPU and memory load, and fine-tuning connection pooling, we’ve kept utilization low and unlocked roughly 10x more connections per database. This gives us plenty of headroom to spin up extra processing capacity, maintain resilient standby servers, and quickly deploy new workloads. We also added support for self-hosted databases to power short-term, trial, and testing accounts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;platform-engineering-operations-and-building-the-team&quot;&gt;Platform engineering, operations and building the team&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;We opened up more of our APIs. Some now power unmanned robots, new experiences, and workflows beyond what we imagined internally. We plan to open up even more, in a structured way, so agents online and MCP servers can start interacting directly with us.&lt;/li&gt;
  &lt;li&gt;Observability, performance audits, and our release processes are getting sharper with each new line of code we ship. We now log, trace (distributed!), and observe millions of requests every day across many many services.&lt;/li&gt;
  &lt;li&gt;Engineering onboarding for new tenants—from provisioning compute, storage, networks, accounts, and all scaffolding—now happens in just seconds, down from tens of minutes. This lets us instantly spin up new tenants and saves time across the board.&lt;/li&gt;
  &lt;li&gt;Expanded the team with some fresh, sharp engineers—and streamlined our onboarding, getting them shipping code to production by their second day.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;ai&quot;&gt;AI&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;We joined Google’s AI‑First Accelerator, giving us access to mentorship and space to experiment with AI. We’ve since rolled out use cases—covering product copy generation, marketing tools, auto-coursing, and insights. Most importantly, it unlocked the technical capabilities we needed to integrate AI workflows into our systems, and sparked the conviction to explore more of what’s possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We ship a lot, deploy multiple times a day, and add new restaurants every week. Everything we build is operationally critical, so consistently getting things right matters even more and takes a ton of effort. Nothing is ever truly finished and there’s a lot more to do which is uncomfortably exciting.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;whats-next&quot;&gt;What’s next&lt;/h3&gt;

&lt;p&gt;Restaurant needs keep changing. More features, more integrations, new workflows—some we didn’t expect to build this early. We stay close to where they are and ready for where they’re going.&lt;/p&gt;

&lt;p&gt;Our mission is simple: &lt;strong&gt;to help restaurants focus on things that matter&lt;/strong&gt;. Restaurant business models are fundamentally changing as everything moves online, and seamless experiences across online and offline commerce have become crucial. We believe the best way to support restaurants in this shift is by building an open platform that easily integrates with everything they need—this openness is our competitive advantage.&lt;/p&gt;

&lt;p&gt;To execute this, we continue to invest in Atlas’s core: a unified source of truth with an ecosystem of features that work magically across all sales channels. It gets stronger with every restaurant that joins, accelerates adoption and innovation through open APIs, and cuts operating costs as they use more of it—driving overall software costs down for everyone.&lt;/p&gt;

&lt;p&gt;This time, we’re building with more AI in the stack. Internally, the goal is to make it easier for everyone at Atlas—not just engineers—to build and contribute. Lower the barrier, unlock more experiments, and move faster. Externally, we’re focused on building more experiences, adding and improving workflows, perfecting everyday interactions, opening up more APIs and bringing AI to restaurants where it can truly help.&lt;/p&gt;

&lt;p&gt;YC always reminds us to stay focused on the product and customers—and that’s exactly what we’re doing.&lt;/p&gt;

&lt;p&gt;That’s all for now—thanks for reading this monologue.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;PS: I spend lots of time on infrastructure and engineering operations—happy to swap notes if you’re tackling similar problems. We’re also deep into AI-powered workflows now and would love to learn from folks who’ve done it well. (Email’s open at &lt;a href=&quot;mailto:hey@twkrr.com&quot;&gt;hey@twkrr.com&lt;/a&gt;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Cloud Run; Learnings, hacks and tips</title>
   
      <link href="https://twkrr.com/2023/09/23/cloud-run-research/"/>
   
   <updated>2023-09-23T00:00:00-05:00</updated>
   <id>https://twkrr.com/2023/09/23/cloud-run-research</id>
   <content type="html">&lt;p&gt;Over the past few weeks, I have been working on enhancing the efficiency of our computing resources which are hosted on Cloud Run. The aim was to improve the cold start and reduce cloud spending.&lt;/p&gt;

&lt;p&gt;In this blog post, I would like to share some of the learnings, hacks and tips that I have discovered during this exercise.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;learnings&quot;&gt;Learnings&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://twitter.com/steren/status/1509033666738999297?s=20&quot;&gt;How to measure the cold starts?&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Use container startup latency to measure cold start&lt;/p&gt;

  &lt;p&gt;Time between when an instance is started and when it’s ready to receive requests&lt;/p&gt;

  &lt;p&gt;This latency is primarily influenced by what your code does at startup, so now go optimize&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://cloud.google.com/blog/products/serverless/announcing-startup-cpu-boost-for-cloud-run--cloud-functions&quot;&gt;Why minimum instances doesn’t always solve the problem&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Minimum instances can be used to remove the cold-start encountered when going from zero to one instance, but min-instances aren’t a solution for all cold-starts as traffic scales out to higher numbers of instances. As part of our continued efforts to give you more control over cold start latency, startup CPU boost can help speed up every cold start.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://twitter.com/steren/status/1570638621736308739?s=20&quot;&gt;Why use startup CPU boost over min instances&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Min instance is here mainly for the “0 &amp;gt; 1” case and completely eliminates cold starts&lt;/p&gt;

  &lt;p&gt;Startup CPU Boost is here for N &amp;gt; N+1 and speeds up cold starts but does not eliminate them.&lt;/p&gt;

  &lt;p&gt;Use both, notably because CPU Boost doesn’t impact your bill much.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://cloud.google.com/run/docs/container-contract#responses&quot;&gt;How request timeout setting works&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For Cloud Run services, your container must send a response within the time specified in the request timeout setting after it receives a request, including the container startup time. Otherwise the request is ended and a 504 error is returned.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://cloud.google.com/run/docs/container-contract#startup&quot;&gt;Container lifecycle&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Instances must listen for requests within 4 minutes after being started and all containers within the instance need to be healthy.&lt;/p&gt;

  &lt;p&gt;A request waiting for an instance to start will be kept in a queue for a maximum of 10 seconds&lt;/p&gt;

  &lt;p&gt;If one or more Cloud Run containers exceed the total container memory limit, the instance is terminated. All requests that are still processing on the instance end with an HTTP 500 error.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://cloud.google.com/run/docs/troubleshooting#serving&quot;&gt;Cloud Run serving errors&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Code&lt;/th&gt;
      &lt;th&gt;Reason&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;HTTP 401&lt;/td&gt;
      &lt;td&gt;Client is not authenticated properly&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HTTP 403&lt;/td&gt;
      &lt;td&gt;Client is not authorized to invoke or call the service&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HTTP 404&lt;/td&gt;
      &lt;td&gt;Not Found&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HTTP 429&lt;/td&gt;
      &lt;td&gt;No available container instances&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HTTP 500&lt;/td&gt;
      &lt;td&gt;Cloud Run couldn’t manage the rate of traffic&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HTTP 500 / HTTP 503&lt;/td&gt;
      &lt;td&gt;Container instances are exceeding memory limits&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HTTP 503&lt;/td&gt;
      &lt;td&gt;Malformed response or container instance connection issue&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HTTP 503&lt;/td&gt;
      &lt;td&gt;Unable to process some requests due to high concurrency setting&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HTTP 504&lt;/td&gt;
      &lt;td&gt;Gateway timeout error&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://cloud.google.com/run/pricing&quot;&gt;How pricing works in Cloud Run&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We are paying for CPU, memory and the traffic sent to the client from your application (egress traffic).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tier 2 pricing (in USD)&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Resource&lt;/th&gt;
      &lt;th&gt;Free Tier&lt;/th&gt;
      &lt;th&gt;Charged Rate&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;CPU&lt;/td&gt;
      &lt;td&gt;100 milliseconds&lt;/td&gt;
      &lt;td&gt;$0.00003360 per vCPU-second&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Memory&lt;/td&gt;
      &lt;td&gt;128 MB&lt;/td&gt;
      &lt;td&gt;$0.00000350 per GB-second&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;hacks-vs-impact-on-cost-to-keep-the-instances-warm&quot;&gt;Hacks (vs impact on cost) to keep the instances warm&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Min instances (affects pricing)&lt;/li&gt;
  &lt;li&gt;CPU boost (apparently doesn’t affect pricing)&lt;/li&gt;
  &lt;li&gt;Periodically ping servers (infrastructure overhead)
    &lt;ul&gt;
      &lt;li&gt;You can also work around “cold starts” by periodically making requests to your Cloud Run service which can help prevent the container instances from scaling to zero. For this, use &lt;a href=&quot;https://cloud.google.com/scheduler?utm_campaign=CDR_ahm_aap-severless_cloud-run-faq_&amp;amp;utm_source=external&amp;amp;utm_medium=web&quot;&gt;Google Cloud Scheduler&lt;/a&gt; to make requests every few minutes.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.reddit.com/r/googlecloud/comments/gdb2r7/comment/fpgw0ba/?utm_source=share&amp;amp;utm_medium=web2x&amp;amp;context=3&quot;&gt;Not recommended because its not only one container used, you are not assured that request ‘n’ and ‘n + 1’ reach the same container instance. Even with pre-warming.&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.reddit.com/r/googlecloud/comments/gdb2r7/comment/g7uvn1u/?utm_source=share&amp;amp;utm_medium=web2x&amp;amp;context=3&quot;&gt;Or may be not&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;SIGTERM / SIGKILL infinite loop&lt;/li&gt;
&lt;/ul&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;tips-for-performance-optimisation&quot;&gt;Tips for performance optimisation&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Minimize the number and size of the dependencies that your app loads&lt;/li&gt;
  &lt;li&gt;Keep your app’s “time to listen for requests” startup time short&lt;/li&gt;
  &lt;li&gt;Prevent your application process from crashing&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cloud.google.com/run/docs/tips/general#minimize-container&quot;&gt;The size of your container image has almost no impact on cold starts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://cloud.google.com/run/docs/tips/general&quot;&gt;Cloud Run development tips&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cloud.google.com/run/docs/configuring/cpu#startup-boost&quot;&gt;How CPU boost works on Cloud Run&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ahmetb/cloud-run-faq&quot;&gt;Cloud Run FAQ&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.infoq.com/news/2022/09/google-startup-cpu-boost/&quot;&gt;Cloud Run startup boost&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.reddit.com/r/googlecloud/comments/nq2811/cloud_run_reducing_cold_start_latency_options/&quot;&gt;Reducing cold start latency on Cloud Run&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Brunello Cucinelli</title>
   
      <link href="https://twkrr.com/2023/09/01/brunello-cucinelli/"/>
   
   <updated>2023-09-01T00:00:00-05:00</updated>
   <id>https://twkrr.com/2023/09/01/brunello-cucinelli</id>
   <content type="html">&lt;p&gt;Some notes from &lt;a href=&quot;https://om.co/2015/04/27/brunello-cucinelli-2/&quot;&gt;Brunello Cucinelli’s interview with Om Malik in 2015&lt;/a&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;on-personal-growth-and-authenticity&quot;&gt;On personal growth and authenticity&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Man needs dignity even more than he needs bread.&lt;/li&gt;
  &lt;li&gt;In order to be credible, you must be authentic and true. To be credible, you must be consistent in the way you behave.&lt;/li&gt;
  &lt;li&gt;I do not like things to go too quickly. I like to be swift as a person, but I don’t like things to be rushed lightheartedly.&lt;/li&gt;
  &lt;li&gt;You should go with the flow of mankind, you should live as if it was the last day of your life, plan as if you were to live forever, you should be at rest, at peace, you should give yourself some peace.&lt;/li&gt;
&lt;/ul&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;on-ethics-and-transparency&quot;&gt;On ethics and transparency&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Mankind is becoming more ethical, but it is not happening because man has decided to become better than he was 100 years ago. It’s because we know we live in a glass house where everybody can see.&lt;/li&gt;
  &lt;li&gt;We hold a meeting here with all the staff every two months. Everybody takes part in it. Even the person with the humblest tasks knows exactly what was the latest shop we opened. Everything is based on esteem, and esteem then generates creativity. Everything is visible, when things go well and also when they go less well. When we are sad, when we are worried, when we are happy: If you show all these different moods, then you are credible.&lt;/li&gt;
&lt;/ul&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;on-technology-and-information&quot;&gt;On technology and information&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;We have now swapped information for knowledge, which is not the same thing. I do not want to know. I’m not online. I don’t even have a computer.&lt;/li&gt;
  &lt;li&gt;We must be on the cutting edge with technology. But your life shouldn’t change as a consequence.&lt;/li&gt;
&lt;/ul&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;on-business-and-work-ethic&quot;&gt;On business and work ethic&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Here, no meetings with mobile phones. No one is allowed to bring them into the meeting room. You must look me in the eye. You must know things by heart. You must know all of your business with a 1 to 2 percent error rate. It is also training for your mind.&lt;/li&gt;
  &lt;li&gt;We have more than 50 percent American investors as shareholders. Before going public, I said to them, “Are you looking for a company that grows very fast, that makes profits that are too high, in our view, quick profits? Do not invest in our company. Do you want a company that grows in a gracious way? That allows suppliers to grow alongside it, so that your artisans can grow as well as the company’s staff?”.&lt;/li&gt;
  &lt;li&gt;Say I work for Apple. Maybe I have the humblest kind of job, but I’m not ashamed that I work for Apple. Because it is still Apple. Whereas here in Italy, you say, “I’m a tailor” or “I’m a waiter” and you still get that kind of respect. That’s the nobility that we have to rediscover.&lt;/li&gt;
&lt;/ul&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;on-philosophy&quot;&gt;On philosophy&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Hadrian, the emperor said, “I feel responsible for the beauty in the world.”&lt;/li&gt;
  &lt;li&gt;This century is where enlightenment and romanticism must blend. A great idea that is born out of the mind and then goes through the soul — there is no doubt that the outcome is marvelous. If this idea is true, fair, beautiful, there’s no doubt that it is also a good idea. I think this applies to everything.&lt;/li&gt;
  &lt;li&gt;Any philosopher helps you to raise your head and the world will look better. Respect the human being, and that will be better.&lt;/li&gt;
  &lt;li&gt;The true way to nurture your soul is philosophy. The true malaise of the human being — no matter whether Italian, American, Chinese — is the malaise of your soul, the uneasiness of your soul. This is stronger now than when my father was young or my grandfather.&lt;/li&gt;
  &lt;li&gt;There are three things you cannot buy. Fitness: You have to keep fit, whether you’re rich or not. Diet: You cannot pay someone to be on a diet for you. I think that diet is the biggest sacrifice in my life. Then, looking after your soul. No one can possibly treat your soul but you yourself. This is something you can do through culture and philosophy.&lt;/li&gt;
  &lt;li&gt;Hadrian the emperor said, “I never met anyone who after being paid a compliment did not feel better.”&lt;/li&gt;
&lt;/ul&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Notes from Make Something Wonderful</title>
   
      <link href="https://twkrr.com/2023/04/23/make-something-wonderful/"/>
   
   <updated>2023-04-23T00:00:00-05:00</updated>
   <id>https://twkrr.com/2023/04/23/make-something-wonderful</id>
   <content type="html">&lt;p&gt;A collection of some quotes/notes I stumbled upon while reading the book Make Something Wonderful.&lt;/p&gt;

&lt;p&gt;Make Something Wonderful is a recent release by the folks at &lt;a href=&quot;https://stevejobsarchive.com/&quot;&gt;Steve Jobs Archive&lt;/a&gt;. The book provides a unique look into how Steve Jobs tackled life and work during his time at Apple, NeXT, and Pixar. If you’re interested, you can read the full book online &lt;a href=&quot;https://book.stevejobsarchive.com/&quot;&gt;right here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But for now, here are some of my personal favorite stories and insights from the book.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We make what we think of as the Rolls-Royce of personal computers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We started a little personal-computer manufacturing company in a garage in Los Altos in 1976. Now we’re the largest personal-computer company in the world. We make what we think of as the Rolls-Royce of personal computers. It’s a domesticated computer. People expect blinking lights, but what they find is that it looks like a portable typewriter, which, connected to a suitable readout screen, is able to dis­play in color.&lt;/p&gt;

&lt;p&gt;There’s a feedback it gives to people, and the enthusiasm of the users is tremendous. We’re always asked what it can do, and it can do many things, but in my opinion the real thing it is doing right now is to teach people how to pro­gram the computer.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Computers and society are out on a first date.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the reasons I’m here is because I need your help. If you’ve looked at computers, they look like garbage. All the great product designers are off designing automobiles or buildings. But hardly any of them are designing computers. If we take a look, we’re going to sell 3 million computers this year, 10 million in ’86, whether they look like a piece of shit or they look great. People are just going to suck this stuff up so fast no matter what it looks like. And it doesn’t cost any more money to make them look great. They are going to be these new objects that are going to be in everyone’s working environment, everyone’s educational environment, and everyone’s home environment. We have a shot [at] putting a great object there—and if we don’t, we’re going to put one more piece-of-junk object there.&lt;/p&gt;

&lt;p&gt;By ’86, ’87, pick a year, people are going to spend more time interacting with these machines than they do interacting with automobiles today. People are going to be spending two, three hours a day interacting with these machines—longer than they spend in the car. And so the industrial design, the software design, and how people interact with these things certainly must be given the consideration that we give automobiles today—if not a lot more.&lt;/p&gt;

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

&lt;p&gt;And I think we have a chance with this new computing technology meeting people in the eighties—the fact that computers and society are out on a first date in the eighties. We have a chance to make these things beautiful, and we have a chance to communicate something through the design of the objects themselves.&lt;/p&gt;

&lt;p&gt;When I was going to school, I had a few great teachers and a lot of mediocre teachers. And the thing that probably kept me out of jail was the books. I could go and read what Aristotle or Plato wrote without an intermediary in the way. And a book was a phenomenal thing. It got right from the source to the destination without anything in the middle.&lt;/p&gt;

&lt;p&gt;The problem was, you can’t ask Aristotle a question. And I think, as we look towards the next fifty to one hundred years, if we really can come up with these machines that can capture an underlying spirit, or an underlying set of principles, or an underlying way of looking at the world, then, when the next Aristotle comes around, maybe if he carries around one of these machines with him his whole life—his or her whole life—and types in all this stuff, then maybe someday, after this person’s dead and gone, we can ask this machine, Hey, what would Aristotle have said? What about this? And maybe we won’t get the right answer, but maybe we will. And that’s really exciting to me. And that’s one of the reasons I’m doing what I’m doing.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;People don’t want to program computers. People want to use computers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Apple’s strategy is really simple. What we want to do is put an incredibly great computer in a book that you carry around with you, that you can learn how to use in twenty minutes. That’s what we want to do. And we want to do it this decade. And we really want to do it with a radio link in it so you don’t have to hook up to anything—you’re in communication with all these larger databases and other computers. We don’t know how to do that now. It’s impossible technically&lt;/p&gt;

&lt;p&gt;We’re trying to get away from programming. We’ve got to get away from programming because people don’t want to program computers. People want to use computers.&lt;/p&gt;

&lt;p&gt;You can hook up to the source and, you know, do whatever you’re going to do. Meet women, I don’t know. But other than that, there’s no good reason to buy one for your house right now. But there will be. There will be.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You work for Apple first and your boss second&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I don’t think finance is what drives people at Apple. I don’t think it’s money, but feeling like you own a piece of the company, and this is your damn company, and if you see something … We always tell people, You work for Apple first and your boss second. We feel pretty strongly about that.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Macintosh lets you sing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that’s what Macintosh is all about. It’s the first telephone of our industry. But the neatest thing about it to me is, the same as the telephone to the telegraph, Macintosh lets you sing. It lets you use special fonts. It lets you make drawings and pictures or incorporate other people’s drawings or pictures into your documents.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When you make things smaller, you have the ability to make them more precisely&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I want to build products that are inherently smaller than any of the products on the market today. And when you make things smaller, you have the ability to make them more precisely. Obviously, a perfect example of that is a watch. It’s beautiful, but the precision has to be the scale of the object itself, and so you make it very precise. And as our products get smaller, we have the opportunity to do that. So, obviously, I would like everything to be smaller.&lt;/p&gt;

&lt;p&gt;I also think that it’s really nice to be able to carry products around. Even if they’re not portable, it’s very nice to be able to have a handle on them that says, Pick me up and move me when you want to change where I am. Carry them from room to room, or from office to office. Lisa’s too heavy to carry from office to office, or room to room, or home on the weekends. So the question is, How do we find a way to package that same functionality into something that we can carry around with us and that is smaller, obviously—and be able to express the form of that more precisely? That’s where we’re going in the future, those directions.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I just get to be really stubborn about making things as good as we all know they can be&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I don’t think my taste in aesthetics is that much different than a lot of other people’s. The difference is that I just get to be really stubborn about making things as good as we all know they can be. That’s the only difference.&lt;/p&gt;

&lt;p&gt;Things get more refined as you make mistakes. I’ve had a chance to make a lot of mistakes. Your aesthetics get better as you make mistakes. But the real big thing is: if you’re going to make something, it doesn’t take any more energy—and rarely does it take more money—to make it really great. All it takes is a little more time. Not that much more. And a willingness to do so, a willingness to persevere until it’s really great.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Man, I want to build things.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I want to build things. I’m thirty. I’m not ready to be an industry pundit. I got three offers to be a professor during this summer, and I told all of the universities that I thought I would be an awful professor. What I’m best at doing is finding a group of talented people and making things with them. I respect the direction that Apple is going in. But for me personally, you know, I want to make things. And if there’s no place for me to make things there, then I’ll do what I did twice before. I’ll make my own place. You know, I did it in the garage when Apple started, and I did it in the metaphorical garage when Mac started&lt;/p&gt;

&lt;p&gt;Though the outside world looks at success from a numer­ical point of view, my yardstick might be quite different than that. My yardstick may be how every computer that’s designed from here on out will have to be at least as good as a Macintosh.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I think a tremendous amount of goods and services is going to be sold, or at least the demand created for such things, over the web.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think most large companies and medium-size companies (and even small companies) are starting to look at the web as the ultimate direct-to-customer distribution chain, bypassing all middlemen, going directly from the supplier to the consumer. That’s a pretty powerful concept when you think about it. One of the things that I love is that a very small company, if they invest a lot in their website, can look just as formidable and just as solid on the web as a very large company can. As a matter of fact, some of the smaller companies are more hip on the web, getting more hip to the web sooner, and so they actually look better than some of the large companies do right now. It’s going to be this very leveling phenomenon, but I think a tremendous amount of goods and services is going to be sold, or at least the demand created for such things, over the web.&lt;/p&gt;

&lt;p&gt;There’s a lot of things happening with the web right now, in terms of allowing people access to information that they would just never have before. What this does is, of course, it lets special-interest groups get together. I know people who have had, as an example, a stroke, and have gotten on the web and found that there are several web pages now devoted to information for stroke victims where they can learn about some of the latest treatments. They can learn about avoidance, the latest in avoidance advice, and things like that. Those things didn’t exist before, as well.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of your life as a rainbow arcing across the horizon of this world. You appear, have a chance to blaze in the sky, then you disappear.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What you follow with your heart will indeed come back to make your life much richer.&lt;/p&gt;

&lt;p&gt;But one has no way of knowing which of these paths will lead anywhere in advance. That’s the wonderful thing about it, in a way. The only thing one can do is to believe that some of what you follow with your heart will indeed come back to make your life much richer. And it will. And you will gain an ever firmer trust in your instincts and intuition.&lt;/p&gt;

&lt;p&gt;Don’t be a career. The enemy of most dreams and intuitions, and one of the most dangerous and stifling concepts ever invented by humans, is the Career. A career is a concept for how one is supposed to progress through stages during the training for and practicing of your working life.&lt;/p&gt;

&lt;p&gt;Think of your life as a rainbow arcing across the horizon of this world. You appear, have a chance to blaze in the sky, then you disappear.&lt;/p&gt;

&lt;p&gt;Regrets are most often things you didn’t do, and wish you did. I still regret not kissing Nancy Kinniman in high school. Who knows what might have happened? Maybe she regrets it too …&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We don’t take anybody for granted&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every single day we worry about how we can make Pixar a better company so that nobody will ever want to leave, and so we don’t take anybody for granted. Because if they don’t want to be at Pixar, then probably they should leave anyway—whether or not they would ever have a contract. &lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are no shortcuts around quality, and quality starts with people.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You’d better have great people, or you won’t get your product to market as fast as possible. Or you might get a product to market really fast, but it will be really clunky and nobody will buy it. There are no shortcuts around quality, and quality starts with people. Maybe shortcuts exist, but I’m not smart enough to have ever found any.
I spend 20 percent of my time recruiting, even now. I spend a day a week helping people recruit. It’s one of the most important things you can do.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The worst thing that someone can do in an interview is to agree with me&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ultimately there are two paths. If a candidate has been in the workplace for a while, you have to look at the results. There are people who look so good on paper and talk such a good story but have no results behind them. They can’t point to breakthroughs or successful products that they shipped and played an integral part in. Ultimately the results should lead you to the people. As a matter of fact, that’s how I find great people. I look at great results and I find out who was responsible for them.
However, sometimes young people haven’t had the opportunity yet to be in a position of influence to create such results. So here you must evaluate potential. It’s certainly more difficult, but the primary attributes of potential are intelligence and the ability to learn quickly. Much of it is also drive and passion—hard work makes up for a lot.&lt;/p&gt;

&lt;p&gt;Many times in an interview I will purposely upset someone: I’ll criticize their prior work. I’ll do my homework, find out what they worked on and say, God, that really turned out to be a bomb. That really turned out to be a bozo product. Why did you work on that? I shouldn’t say this in your book, but the worst thing that someone can do in an interview is to agree with me and knuckle under.&lt;/p&gt;

&lt;p&gt;What I look for is for someone to come right back and say, You’re dead wrong and here’s why. I want to see what people are like under pressure. I want to see if they just fold or if they have firm conviction, belief, and pride in what they did. It’s also good every once in a while to really piss somebody off in an interview to see how they react because, if your company is a meritocracy of ideas, with passionate people, you have a company with a lot of arguments. If people can’t stand up and argue well under pressure, they may not do well in such an environment.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Life is short; don’t waste it. Tell the truth. Technology should enhance human creativity. Process matters. Beauty matters. Details matter. The world we know is a human creation—and we can push it forward.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As CEO of Apple and Pixar (he held both roles until Disney acquired Pixar in 2006), he saw his job as number one, re­­­cruit; number two, set an overall direction; and number three, inspire and cajole and persuade. He said, You’re not grabbing the pencil out of the twenty-five-year-old’s hand to do it better than they are. If you’re smart, you’re hiring twenty-five-year-olds who are smarter than you. He gave particular thought to his responsibility for the business aspects of a creative company. A risk-taking creative environment on the product side, he said, required a fiscally conservative environment on the business side. Creative people are willing to take a leap in the air, but they need to know that the ground’s going to be there when they get back.&lt;/p&gt;

&lt;p&gt;Steve saw every product and film as a way of expressing to the rest of our species our deep appre­ciation. Apple technology offered tools to make something wonderful. And Pixar films, he believed, had the rare opportunity to put stories into the culture, stories that would speak to our grandkids’ grandkids’ grandkids.&lt;/p&gt;

&lt;p&gt;It is always a team of people, and the chemistry between that team of people, that makes great results, Steve once said. Under his leadership, the teams at Apple and Pixar transformed four very different industries: computing, telecommunications, music, and film. The engine driving these trans­formations was a remarkably consistent set of values that Steve held dear: Life is short; don’t waste it. Tell the truth. Technology should enhance human creativity. Process matters. Beauty matters. Details matter. The world we know is a human creation—and we can push it forward.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We will let the customer tell us what they want, and we will respond to it super fast.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’re having to make guesses four or five, six months in advance, about what the customer wants. We’re not smart enough to do that. I don’t think Einstein’s smart enough to do that. So what we’re going to do is get really simple and start taking inventory out of those pipelines so we can let the customer tell us what they want, and we can respond to it super fast. You’re going to see us be doing a lot of things like that. Today is just the first of many things we’re going to be doing with you.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Marketing is about values&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We started working about eight weeks ago. The question we asked was, Our customers want to know: Who is Apple, and what is it that we stand for? Where do we fit in this world? And what we’re about isn’t making boxes for people to get their jobs done, although we do that well. We do that better than almost anybody, in some cases. But Apple is about something more than that. Apple, at the core—its core value—is that we believe that people with passion can change the world for the better. That’s what we believe.&lt;/p&gt;

&lt;p&gt;But the best example of all, and one of the greatest jobs of marketing that the universe has ever seen, is Nike. Re­member: Nike sells a commodity! They sell shoes! And yet when you think of Nike, you feel something different than a shoe company. In their ads, as you know, they don’t ever talk about the products. They don’t ever tell you about their air soles, and why they are better than Reebok’s air soles. What does Nike do in their advertising? They honor great athletes, and they honor great athletics. That’s who they are. That’s what they are about.&lt;/p&gt;

&lt;p&gt;And we believe that in this world, people can change it for the better. And that those people that are crazy enough to think that they can change the world are the ones that actually do.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Apple’s reason for being&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Apple is the premier company in the world at making the exploding world of high technology easy to learn and use, thereby enabling mere mortals to enrich their lives using it.&lt;/p&gt;

&lt;p&gt;Demystified technology, it will have a much greater impact than any other thing we can do. The stores need to be thought of as a mecca for understanding technology and making all of the digits a part of your life. All things digital, digital music, digital photography, people who’ve migrated to broadband, people/families who want to build a home network&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Excellence&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We are what we repeatedly do. Excellence, then, is not an act, but a habit. – Aristotle&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I think I got lucky and had the chutzpah to call these guys up.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I called up him and Andy and a few other people, Jerry Sanders [the founder of microchip company AMD]. I just called them up and I said, Look, I’m young and I’m trying to run with this company. I’m just wondering if I could buy you lunch once a quarter and pick your brain.&lt;/p&gt;

&lt;p&gt;I think I got lucky and had the chutzpah to call these guys up. However, there are other people who have chutzpah to call people up too. The Google guys called me up, so I had lunch with them. And so I think it still happens a little. I don’t think it ever happened a lot, and I don’t think it happens a lot now. But I think it still happens—it happened a little, and it still happens a little. Maybe most people aren’t interested. They have their own things to worry about.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can’t plan to meet the people who will change your life.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can’t plan to meet the people who will change your life. It just happens. Maybe its random, maybe its fate. Either way, you can’t plan for it. But you want to recognize it when it happens, and have the courage and clarity of mind to grab onto it.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
&lt;strong&gt;We’re only as good as our next picture.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stocks go up and down, and things may be different tomorrow, but I thought it was worth a moment of reflection today. And so it is again.&lt;/p&gt;

&lt;p&gt;Walt Disney used to say to his team: We’re only as good as our next picture. Well, we’re only as good as our next amazing new product.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Everything around you that you call life was made up by people that were no smarter than you.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Life can be much broader once you discover one simple fact—and that is: everything around you that you call life was made up by people that were no smarter than you.&lt;/p&gt;

&lt;p&gt;And you can change it.&lt;/p&gt;

&lt;p&gt;You can influence it.&lt;/p&gt;

&lt;p&gt;You can build your own things that other people can use.&lt;/p&gt;

&lt;p&gt;And the minute you can understand that you can poke life, and if you push in, then something will pop out the other side; that you can change it, you can mold it—that’s maybe the most important thing: to shake off this erroneous notion that life is there, and you’re just going to live in it versus embrace it, change it, improve it, make your mark upon it.&lt;/p&gt;

&lt;p&gt;I think that’s very important, and however you learn that, once you learn it, you’ll want to change life and make it better. Because it’s kind of messed up in a lot of ways.&lt;/p&gt;

&lt;p&gt;Once you learn that, you’ll never be the same again.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Logging in Cloudflare Workers with Sentry</title>
   
      <link href="https://twkrr.com/2022/03/06/cf-workers-logging/"/>
   
   <updated>2022-03-06T00:00:00-06:00</updated>
   <id>https://twkrr.com/2022/03/06/cf-workers-logging</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://atlas.kitchen/&quot;&gt;Atlas&lt;/a&gt; uses Cloudflare Workers to build the routing layer, a simple API app (like DNS) to redirect requests to the correct destinations. It’s a critical piece of our infrastructure. We already have around five routers mapping requests from different services we use for the platform. I previously discussed how we developed with Workers &lt;a href=&quot;https://surendharreddy.dev/2021/10/16/building-with-cf-workers/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Workers provide us with some basic logging but have some limitations:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Workers platform will capture all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console.log&lt;/code&gt; ‘s, and that’s all. It’s inefficient but straightforward, which makes it hard to debug.&lt;/li&gt;
  &lt;li&gt;Logs are not persistent, they are not stored, and we can start and stop the stream at any time to view them.&lt;/li&gt;
  &lt;li&gt;Logs will not display if the Worker’s requests per second are over 200 for the last 5 minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Insufficient logging and tracing have always been a problem we faced with Workers. Working with external systems like payment processors and other integrations made this problem more severe and forced us to solve it. I recently got my hands on solving this problem and thought to share some of our findings and solution with you, hoping this will benefit some of you.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;logging-tools&quot;&gt;Logging tools&lt;/h2&gt;

&lt;p&gt;There are a ton of logging tools out in the market that support Javascript logging, and a few of them support logging on Workers platform. &lt;sup id=&quot;fnref:fn-1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;We picked Sentry because it has excellent Javascript support, and we are already using it for most of our front-end applications. Sentry Javascript doesn’t support out-of-the-box, and we ended up using Robert Cepa’s &lt;a href=&quot;https://github.com/robertcepa/toucan-js&quot;&gt;toucan-js&lt;/a&gt;; it’s a very reliable Sentry client for Workers platform.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;developing-the-application&quot;&gt;Developing the application&lt;/h2&gt;

&lt;p&gt;A quick &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yarn add toucan-js&lt;/code&gt; and a few lines of code we can get started with logging. Here’s how we did it.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generate the application&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;wrangler&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;generate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;https&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;//github.com/cloudflare/worker-template&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Add Webpack to support modules modules.&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;yarn&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;webpack&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Add Sentry with Toucan&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;yarn&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;toucan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Setup the library&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sentry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Toucan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;dsn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SENTRY_DSN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CF_EVENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;workbox&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;
This gets us to a stage where we can start logging anything from the application.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;sentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;captureException&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;To&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;capture&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;errors&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;sentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;captureMessage&lt;/span&gt;   &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;To&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;capture&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;messages&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;sentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addBreadcrumb&lt;/span&gt;    &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;To&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;breadcrumbs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://twkrr.com/assets/sentry-environment.png&quot; /&gt;
  &lt;center&gt; 
    &lt;figcaption&gt;&lt;i&gt;A captured message on Sentry&lt;/i&gt;&lt;/figcaption&gt;
  &lt;/center&gt; 
&lt;/figure&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;But what we needed was more:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;We wanted to tag each release to segregate errors and logs easily&lt;/li&gt;
  &lt;li&gt;We wanted to upload source maps for each release, so we can easily debug errors&lt;/li&gt;
  &lt;li&gt;We wanted to repeat the above steps on our CI/CD pipelines&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both 1 and 2 are configurable on Sentry. We can use &lt;a href=&quot;https://docs.sentry.io/platforms/javascript/sourcemaps/uploading/webpack/&quot;&gt;Sentry’s webpack plugin&lt;/a&gt; to upload source maps and set release and environment details when initialising the client.&lt;/p&gt;

&lt;p&gt;We need to provide authentication token, organisation, and project in the webpack plugin config. We also set release information, ideally accessible as host environment variables. But &lt;a href=&quot;https://developers.cloudflare.com/workers/platform/environment-variables&quot;&gt;environment variables&lt;/a&gt; work differently in Cloudflare workers; we can declare variables on the Workers toml file but cannot override when dynamically deploying the application from our CI/CD executor (and we also don’t want to hardcode secrets).&lt;/p&gt;

&lt;p&gt;The hack we found here was to use Webpack’s &lt;a href=&quot;https://webpack.js.org/plugins/environment-plugin/&quot;&gt;environment-plugin&lt;/a&gt; and access &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process.env&lt;/code&gt; variables in the application. CI/CD executor and Workers platform can read these environment variables. Here’s how we did it.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add Sentry webpack plugin&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;yarn&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dev&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;sentry&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/webpack-plugi&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;n
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Update webpack config and add necessary environment variables&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;EnvironmentPlugin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;webpack&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SentryWebpackPlugin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@sentry/webpack-plugin&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;webworker&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./index.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;devtool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hidden-source-map&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;EnvironmentPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ENVIRONMENT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;SENTRY_DSN&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;SENTRY_RELEASE&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SentryWebpackPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;authToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SENTRY_AUTH_TOKEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SENTRY_ORG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SENTRY_PROJECT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SENTRY_RELEASE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./dist&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Update Sentry client&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sentry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Toucan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;dsn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SENTRY_DSN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CF_EVENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ENVIRONMENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SENTRY_RELEASE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://twkrr.com/assets/sentry-release.png&quot; /&gt;
  &lt;center&gt; 
    &lt;figcaption&gt;&lt;i&gt;Sentry release&lt;/i&gt;&lt;/figcaption&gt;
  &lt;/center&gt; 
&lt;/figure&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://twkrr.com/assets/sentry-source-map.png&quot; /&gt;
  &lt;center&gt; 
    &lt;figcaption&gt;&lt;i&gt;Sourcemap for a release&lt;/i&gt;&lt;/figcaption&gt;
  &lt;/center&gt; 
&lt;/figure&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;This setup allowed us to set environment variables on the host, automatically tag releases, and upload source maps for any machine – local and CI/CD executors.&lt;/p&gt;

&lt;p&gt;Once we had it up, we got a much clearer view of the errors occurring on the Worker.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://twkrr.com/assets/sentry-error-source-map.png&quot; /&gt;
  &lt;center&gt; 
    &lt;figcaption&gt;&lt;i&gt;Error with source map&lt;/i&gt;&lt;/figcaption&gt;
  &lt;/center&gt; 
&lt;/figure&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;We implemented this solution in one of our routers built using Workers and will extend it to all of our routers soon.&lt;/p&gt;

&lt;p&gt;I published a template &lt;a href=&quot;https://github.com/surendharreddy/cf-sentry-logs&quot;&gt;here&lt;/a&gt; with the same setup if you want to use it.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading. Please feel free to reach out to me (email) if you have any questions and ideas, I’ll be happy to take your feedback, help, and discuss it further.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Notes&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:fn-1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://blog.cloudflare.com/observability-ecosystem/ &lt;a href=&quot;#fnref:fn-1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Year in review: 2021</title>
   
      <link href="https://twkrr.com/2021/12/31/year-in-review/"/>
   
   <updated>2021-12-31T00:00:00-06:00</updated>
   <id>https://twkrr.com/2021/12/31/year-in-review</id>
   <content type="html">&lt;p&gt;2021 was yet another decent year for me. I did learn about more things, acquired new interests, and persisted in my hobbies — code, read, learn new things, and meet interesting people.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;atlas-and-y-combinator&quot;&gt;Atlas and Y Combinator&lt;/h2&gt;

&lt;p&gt;Atlas went live this year! We started writing code for it early this year (first commit on 12th Jan!) and processed the first order on 12th May.&lt;/p&gt;

&lt;p&gt;I spent the bulk of 2021 building Atlas. I developed the software, deployed the systems (sometimes physically at the stores), supported our merchants, and continued building some good relationships along the way. It was fun and challenging; I’m still learning how to deal with ambiguity and find clarity, managing myself to be more effective in my role.&lt;/p&gt;

&lt;p&gt;Atlas has pushed me to the edge of my comfort zone and forced me to learn more things this year, not just on the engineering side but also personally — learning to talk to customers, understanding the on-ground operational issues, and business finance side of things.&lt;/p&gt;

&lt;p&gt;And… we also got into Y Combinator (S21 batch). It’s a good validation for us and a huge personal milestone.&lt;/p&gt;

&lt;h2 id=&quot;more-diverse-engineering&quot;&gt;More diverse engineering&lt;/h2&gt;

&lt;p&gt;This year, I worked more on infrastructure and backend engineering. Before starting Atlas, I focused more on site reliability engineering and picked up every opportunity to learn more about the space and excel at it. Working on Atlas diverted that journey and introduced me to other facets of engineering.&lt;/p&gt;

&lt;p&gt;I picked up Ruby to contribute to the backend, built many internal tools using node, learned about PostgreSQL database management, experimented with new technologies (GraphQL, serverless, edge-side computing), and shipped production software with them.&lt;/p&gt;

&lt;p&gt;One of the other things I started doing more actively this year is to write to other engineers to meet and share learnings.&lt;/p&gt;

&lt;p&gt;Apart from work, I helped build a website for The Pan IIM Alumni of Singapore’s &lt;a href=&quot;https://breathe-life-into-india.netlify.app&quot;&gt;Breathe Life Into India&lt;/a&gt; campaign to raise money and save lives from COVID in India. Another fun project I worked on this year was https://canwedine.in/ — my co-founder, and I randomly thought of solving Singapore COVID dine-out rules with this app.&lt;/p&gt;

&lt;h2 id=&quot;homecoming-and-a-heritage-walk&quot;&gt;Homecoming and a heritage walk&lt;/h2&gt;

&lt;p&gt;The world is still emerging from the ruins of COVID, we have seen new variants and more prolonged lockdowns this year, but it’s relieving to see everyone get vaccinated and join hands to slow down the spread of the virus and help countries open up for travel.&lt;/p&gt;

&lt;p&gt;Singapore opening up the borders and allowing controlled travel through vaccination lanes was a piece of good news for me. After two years, I took a short break and traveled home to meet my parents and friends; it felt good to physically be present, hang out and catch up with everyone’s life.&lt;/p&gt;

&lt;p&gt;During my short trip, I had an opportunity to go on a heritage walk with two hobbyist historians (&lt;a href=&quot;https://www.instagram.com/travelsofsamwise/?hl=en&quot;&gt;Sam Dalrymple&lt;/a&gt; and &lt;a href=&quot;https://www.instagram.com/thathyderabadiboy/?hl=en&quot;&gt;Yunus Lasania&lt;/a&gt;) to see the Golconda Fort and learn more about Hyderabad. I was thrilled to know that the Persians were the ones who started to build the city, and eventually, Nizam took it over during the time to the Mughals. (History nerd in me wants to talk more about it but will leave it for another day)&lt;/p&gt;

&lt;p&gt;We’re still seeing a rise of new variants like Omicron and countries bringing the restrictions back. But hopefully, with booster shots and more precaution’s we’ll get back to everyday life.&lt;/p&gt;

&lt;h2 id=&quot;learnings-and-life-skills&quot;&gt;Learnings and life skills&lt;/h2&gt;

&lt;p&gt;A lot of work I did this year was purely exploratory — understanding the problem space, figuring out solutions, prototyping, synthesizing the insights/facts from reading demanded a lot of structure and discipline. I struggled a lot during the initial phases to be more effective and add value but got better at it. I’m still learning and definitely in a better place than I started.&lt;/p&gt;

&lt;p&gt;I’ve moved houses twice this year. Packing everything I have and moving between homes made me think deeply about two things, the things I need and how to design a space with more thought. I never invested my time to think about what I needed in my room thoroughly. Doing that once made me realize how you can design/engineer anything in life — I wrote about &lt;a href=&quot;https://surendharreddy.dev/2021/10/28/engineering-happiness/&quot;&gt;engineering happiness&lt;/a&gt; and having &lt;a href=&quot;https://surendharreddy.dev/2021/11/01/perfect-day/&quot;&gt;perfect days&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Staying with housemates forced me to learn some life skills this year; I never had or took care of a pet in my life, but I got to cross that fear now with the help of Eden (friends dog) — yes, I only learned how to keep a dog alive this year.&lt;/p&gt;

&lt;p&gt;I also tried to write a bit more this year; I find deep joy in organizing my thoughts and also sharing my ideas, learnings. I didn’t get time to read as many books as I would like to, but I actively spent time reading a few good long-form articles — tried to capture some compelling thoughts in the stream.&lt;/p&gt;

&lt;h2 id=&quot;new-interests-and-hobbies&quot;&gt;New interests and hobbies&lt;/h2&gt;

&lt;p&gt;Netflix’s “Formula 1: Drive to Survive” got me hooked onto the motor racing sport this year; I think it’s one of the best sports documentaries I’ve ever watched. After completing this show in May, I hardly missed watching a race, started watching it in the middle of the tournament (from the Portuguese Grand Prix), and continued till the end — this was a perfect escape from work during the weekends sometimes.&lt;/p&gt;

&lt;p&gt;This year’s decider was one of the best races I watched! Watching the driver perform at that speed, carefully strategize pit stops, and pace through laps to ascend positions was exciting.&lt;/p&gt;

&lt;p&gt;Along with learning how to keep a dog alive, I also learned how to make a few cocktails.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;There’s been a lot of learnings this year, both personally and professionally. All these life skills are helping me prepare to play long-term games and enabling me to have “the long obedience in the same direction”.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
Thank you for reading.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
I wish you a happy 2022.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Perfect day</title>
   
      <link href="https://twkrr.com/2021/11/01/perfect-day/"/>
   
   <updated>2021-11-01T00:00:00-05:00</updated>
   <id>https://twkrr.com/2021/11/01/perfect-day</id>
   <content type="html">&lt;p&gt;&lt;sup&gt;&lt;strong&gt;Peter Miles:&lt;/strong&gt; Yeah, ‘cause you can’t just push the car hard the whole way, right?&lt;/sup&gt;&lt;br /&gt;
&lt;sup&gt;&lt;strong&gt;Ken Miles:&lt;/strong&gt; That’s right. You have to be kind to the car. You feel the poor thing groaning underneath you. If you’re going to push a piece of machinery to the limit, and expect it to hold together, you have to have some sense of where that limit is. Look out there. Out there is the perfect lap. No mistakes. Every gear change, every corner, perfect. You see it?&lt;/sup&gt;&lt;br /&gt;
&lt;sup&gt;&lt;strong&gt;Peter Miles:&lt;/strong&gt; I think so.&lt;/sup&gt;&lt;br /&gt;
&lt;sup&gt;&lt;strong&gt;Ken Miles:&lt;/strong&gt; Most people can’t. Most people don’t even know it’s out there, but it is. It’s there.&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=pLHmFnim1Ws&quot;&gt;This&lt;/a&gt;&lt;sup id=&quot;fnref:fn-1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; particular scene from the Ford vs. Ferrari movie has stuck with me for a long time. I have always used this as a frame of reference to explain perfect moments in life that are not obvious to many of us.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;While walking Eden, my housemate’s dog, I was thinking about my day and realized I had one of these perfect laps (days) today.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
A perfect workday is when I have the right balance of exploration, challenge, and outcomes in the activities I choose to do.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I managed to fix and release a few tiny bugs and a new feature for Atlas.&lt;/li&gt;
  &lt;li&gt;I solutioned a feature to capture refunds for every transaction on the Atlas platform to help merchants reconcile financial reports.&lt;/li&gt;
  &lt;li&gt;One of our merchants launched their marketing campaigns, which resulted in the highest sales we ever made on the platform — this was also a great day to monitor the infrastructure and understand what type of surge in traffic we could handle. I learned how to tune our serverless Cloud Run&lt;sup id=&quot;fnref:fn-2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; instances to be more efficient and serve traffic surges like today.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A perfect personal day is when I make time for each of my routines — health, reading and reflecting (writing).&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I ran 3.5 KM and did an adequate chest workout&lt;/li&gt;
  &lt;li&gt;I took Eden out for a walk — she peed and pooped (this is my &lt;a href=&quot;https://surendharreddy.dev/2021/10/28/engineering-happiness/&quot;&gt;private victory&lt;/a&gt;&lt;sup id=&quot;fnref:fn-3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;)&lt;/li&gt;
  &lt;li&gt;I wrote this post&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A perfect social day is when I make time to think about family/friends and attend to their messages or catch up with them.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I made time to checked in with family and few friends&lt;/li&gt;
  &lt;li&gt;I got back to every person who messaged me today&lt;/li&gt;
  &lt;li&gt;I initiated few new conversations to plan for upcoming weeks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;
Today felt like a perfect day; it was balanced by good learnings, outcomes, and some quality social and personal time.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Not all days are the same and are perfect; it’s hard to sustain these levels every day. But constantly optimizing and prioritizing things will pave a path for more of these perfect laps — the idea is to score as many perfect laps as you can and have a good race.&lt;/p&gt;

&lt;p&gt;What does a perfect day look like for you?&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Notes&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:fn-1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://www.youtube.com/watch?v=pLHmFnim1Ws &lt;a href=&quot;#fnref:fn-1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://cloud.google.com/run &lt;a href=&quot;#fnref:fn-2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://surendharreddy.dev/2021/10/28/engineering-happiness/ &lt;a href=&quot;#fnref:fn-3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Engineering happiness</title>
   
      <link href="https://twkrr.com/2021/10/28/engineering-happiness/"/>
   
   <updated>2021-10-28T00:00:00-05:00</updated>
   <id>https://twkrr.com/2021/10/28/engineering-happiness</id>
   <content type="html">&lt;p&gt;&lt;em&gt;“Inaction breeds doubt and fear. Action breeds confidence and courage. If you want to conquer the negative elements in your life, don’t sit at home and think about it. Go out and get busy!” — Dale Carnegie&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The natural course of things is decay and chaos. Pretty much every living thing we can imagine without any action will end up dying, and the only way out is to bring some form of order to it. Essentially, you won’t be able to avoid the decay, but you’ll prolong its life.&lt;/p&gt;

&lt;p&gt;It’s been about 18 months since I last stepped out of Singapore. In March 2020, I went to Taiwan for a short break and got back right before the pandemic took over the world.&lt;/p&gt;

&lt;p&gt;Travel is a big part of my life; it is one of my favorite activities. Every year, I intentionally take breaks to travel to new places to learn about the site, try new things and break out of my daily life.&lt;/p&gt;

&lt;p&gt;Not being able to meet family, friends for almost two straight years made me unhappy. It’s still not predictable when we can travel, restrictions-free.&lt;/p&gt;

&lt;p&gt;Getting vaccinated gave me some hope about countries opening up for travel, but soon we saw a rise in new variants – many places noticed the increase of cases during the second wave, which halted my plans one more time. There has been a significant fluctuation in my expectations the last few months, and it still looks blurry about how it’ll all end.&lt;/p&gt;

&lt;p&gt;Processing all these feelings made me realize that it’s a slippery slope – like a bad trip. Pretty much all travel-related activities got paused, social gatherings were limited to smaller groups, and personal activities (gyms, etc.) were asked to close for a few months and left us with nothing much to do. This period was challenging; it was frustrating – I imagine many of you are in a similar situation and are frustrated about it.&lt;/p&gt;

&lt;p&gt;Lately, I’ve been thinking a lot about it and trying to figure out maintainable solutions to direct my emotions away from it and focus on the right moments. I realized happiness is a skill; it’s something you can design/engineer. It’s practically possible to squeeze more of life from your time by intentionally creating your life.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Here’s what I do to design for happiness&lt;/p&gt;

&lt;h2 id=&quot;private-victories&quot;&gt;Private victories&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Working on things I care about&lt;/li&gt;
  &lt;li&gt;Scheduled reading of weekends&lt;/li&gt;
  &lt;li&gt;Making time to help friends with their stuff (personal, learning, work)&lt;/li&gt;
  &lt;li&gt;Work on personal projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Being more intentional and disciplined about how I spend my time has significantly improved the quality of my life. Actively managing my time, being an initiator, and following up with things/people is helping me maintain that quality.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;building-routines&quot;&gt;Building routines&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Scheduling time for events with friends (F1 weekends, movie nights, sports)&lt;/li&gt;
  &lt;li&gt;Walking and sometimes taking care of my housemates dog Eden&lt;/li&gt;
  &lt;li&gt;Monthly meetups with friends&lt;/li&gt;
  &lt;li&gt;Weekly calls with family and friends&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building systems (routines) to allocate mind space for things I like doing in life is helping me coexist in all roles as I grow professionally and personally. Again, being more intentional forces me to maximize these interactions.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;disciplined-exploration&quot;&gt;Disciplined exploration&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Cold emails&lt;/li&gt;
  &lt;li&gt;Meetup with new people&lt;/li&gt;
  &lt;li&gt;Wandering on the internet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Being a bit quirky and open-minded introduced me to new people and things in life – I always enjoyed these interactions. I frequently reach out to people on the internet with similar interests/backgrounds and actively try to exchange thoughts.&lt;/p&gt;

&lt;p&gt;The internet is a fantastic place; it’s one of the most significant advantages I have to reach out to any people on this planet. Leveraging it to find new people works all the time — I actively try to reach out to people and hang out in chat rooms to get to know people. It’s fun!&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;These are a few things I started doing to put myself in motion, try new things, and achieve a happy state of mind. It can be different for you, but the lesson is, chaos is the default state of everything, and if you care enough about something, you should do something about it and bring some order by designing for happiness.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Building with Cloudflare Workers</title>
   
      <link href="https://twkrr.com/2021/10/16/building-with-cf-workers/"/>
   
   <updated>2021-10-16T00:00:00-05:00</updated>
   <id>https://twkrr.com/2021/10/16/building-with-cf-workers</id>
   <content type="html">&lt;p&gt;&lt;em&gt;Note: This is an essay about how/why we are using Cloudflare Workers at my current startup Atlas. Skip to part 2 if you want to read only about Workers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Atlas is an operating system for the food and beverage industry; the system is built with few industry-specific considerations; you can read about what/why/how in my previous post &lt;a href=&quot;https://surendharreddy.dev/2021/09/27/currently-working-on/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Technically speaking, it’s a system with an isolated database, compute, and shared routing for each tenant who is a restaurant group owner on the platform. Building a system that supports this requirement is not rocket science; we have seen these patterns and similar software a few times already — architecting a SaaS with support for isolated databases and compute instances is pretty straightforward. The complexity came from the shared routing layer. We explored cloud/serverless functions and API-only routers, but it all had a fair share of problems, cloud functions didn’t have persisted state, and apps required a lot of boilerplate code.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure&gt;
    &lt;figcaption&gt;A sample of Atlas router architecture:&lt;/figcaption&gt;
    &lt;img src=&quot;https://twkrr.com/assets/atlas-router.jpeg&quot; /&gt;
  &lt;/figure&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Our goal was to build a light routing layer that is fast — in short, we want to create something as fast and reliable as DNS for our network. And then, we came across Cloudflare Workers&lt;sup id=&quot;fnref:fn-1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, a serverless platform to deploy lightweight javascript applications, which looked like a good fit.&lt;/p&gt;

&lt;p&gt;Cloudflare Workers allows you to deploy serverless applications instantly across the globe, in 250 cities&lt;sup id=&quot;fnref:fn-2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, and scale it automatically meaning user requests will be served from the nearest point of presence. Cloudflare Workers is powered by V8 isolates&lt;sup id=&quot;fnref:fn-3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; and has zero cold start time&lt;sup id=&quot;fnref:fn-4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. V8 isolates are lightweight contexts that group variables with the code allowed to mutate them.&lt;/p&gt;

&lt;p&gt;Cloudflare announced the Workers platform back in 2017 and has made significant improvements since then.&lt;sup id=&quot;fnref:fn-5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;In this next part, I’ll focus more on how to piece all these things together to build a complete app using Workers.&lt;/p&gt;

&lt;h2 id=&quot;compute-workers--workers-unbound&quot;&gt;Compute (Workers + Workers Unbound)&lt;/h2&gt;

&lt;p&gt;Workers are lightweight V8 isolates that can process every request; think of it as a cloud function but running on this platform powered by V8, a Javascript engine.&lt;/p&gt;

&lt;p&gt;Each Worker ​​will run on a URL that you specified and gets a *.workers.dev domain if you configured it so. A Worker gets invoked when an HTTP request is made on this specified URL. Cloudflare will hijack the call and route the request to Worker for processing. A Worker can listen to these fetch events (HTTP), scheduled events (cron job) and respond with a Response.&lt;/p&gt;

&lt;p&gt;Each Worker has their variables and encrypted secrets, and these values are available inside the script as global variables, which will contain their associated values.&lt;/p&gt;

&lt;p&gt;A program will only get 10ms of CPU time per request on a standard Worker&lt;sup id=&quot;fnref:fn-6&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;, which I think is not ideal for all the tasks. Cloudflare offers Workers Unbound, an extension of Workers, but it is for applications that need longer execution times. It’s a paid feature.&lt;/p&gt;

&lt;p&gt;Workers belong to a zone, a domain, making it slightly challenging to separate dev, staging, or production environments. The hack is to host your environments under a different domain.&lt;/p&gt;

&lt;p&gt;While Workers instance can handle multiple requests including concurrent requests in a single-threaded event loop there’s no guarantee that any two requests will land in the same instance which is why it is advised not to maintain any state inside the Worker event handler — so you need a way to store things.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;storage&quot;&gt;Storage&lt;/h2&gt;

&lt;p&gt;Cloudflare Workers KV powers storage in Cloudflare Workers. Workers KV is a global, low-latency, key-value datastore, and it’s optimized for high read applications.&lt;/p&gt;

&lt;p&gt;One caveat, though — updating the KV record from the dashboard is a bit buggy. This whole UX needs to improve quite a lot, and changes may take up to 60 seconds to propagate to all other edge locations. There’s a limited option if you want to have access to KV namespaces.&lt;/p&gt;

&lt;p&gt;Durable objects are another way to handle storage in Workers, and it provides low-latency coordination and consistent storage for the Workers. Durable Objects are named instances of a class you define. As a class in object-oriented programming, the class defines the methods and data a Durable Object can access.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;operations&quot;&gt;Operations&lt;/h2&gt;

&lt;h3 id=&quot;development-and-deployment&quot;&gt;Development and Deployment&lt;/h3&gt;

&lt;p&gt;Developing on the Workers platform is relatively straightforward; it supports plain Javascript, Webpack builds and supports templates, you can reuse any template. We can preview them on a temporary URL and fully deploy them to the edge using Wrangler CLI&lt;sup id=&quot;fnref:fn-7&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-7&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;You can create multiple environments, bind different KV namespaces, and add secrets using wrangler.toml configuration file. See the &lt;a href=&quot;https://developers.cloudflare.com/workers/cli-wrangler/configuration&quot;&gt;Workers configuration&lt;/a&gt; notes here to know how deeply you can configure the Workers.&lt;/p&gt;

&lt;p&gt;There’s no out-of-the-box solution for testing Workers, and it can get tricky to test KV, secret implementations thoroughly. I found the mini flare&lt;sup id=&quot;fnref:fn-8&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-8&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt; quite helpful to test the Workers.&lt;/p&gt;

&lt;h3 id=&quot;logging-and-tracing&quot;&gt;Logging and tracing&lt;/h3&gt;

&lt;p&gt;Logging has forever been a problem in Workers, but recently they enabled support for console.log, which means we can stream all the logs to debug the code. We can stream the logs from Workers on the dashboard or using a CLI.&lt;/p&gt;

&lt;p&gt;You can use logging tools like Sentry for any production logging, and there are many useful open-source logging modules to serve this purpose.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;community&quot;&gt;Community&lt;/h2&gt;

&lt;p&gt;I love Cloudflare’s community! It’s always fun to hangout in their Discord chat rooms&lt;sup id=&quot;fnref:fn-9&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-9&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;9&lt;/a&gt;&lt;/sup&gt; and learn from everyone there. The blog posts, constant stream of examples makes it super easy for me to figure out things.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Apart from it being a good fit for our platform, there are few more things I like about Workers.&lt;/p&gt;

&lt;h2 id=&quot;faster-deployments&quot;&gt;Faster deployments&lt;/h2&gt;

&lt;p&gt;Deploying Workers is insanely fast. Period.&lt;/p&gt;

&lt;p&gt;Our CI/CD times have significantly improved and we have less friction working with Workers so far.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;easier-onboarding&quot;&gt;Easier onboarding&lt;/h2&gt;

&lt;p&gt;Because it’s simple and modularized, onboarding new engineers and team members onto apps built using Workers is relatively straightforward.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;continuous-improvements-from-cloudflare&quot;&gt;Continuous improvements from Cloudflare&lt;/h2&gt;

&lt;p&gt;I started using Workers when it was still in beta, and since then, they have launched a ton of improvements (profiling, logging), and it did make all of it better. Enjoy it when I see continuous, more minor improvements like these.&lt;/p&gt;

&lt;p&gt;Fun fact; I hosted this site on Workers!&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing thoughts&lt;/h2&gt;

&lt;p&gt;Routing is a primary layer for our infrastructure; relying entirely on Cloudflare might lead us to a single point of failure — we may go down with Cloudflare. There’s been an outage recently on Cloudflare where the dashboard was not accessible for a few minutes, which caused some issues on our end.&lt;/p&gt;

&lt;p&gt;But it’s something we can replicate on every platform, but Cloudflare seems like a good fit so far. The hack was to run the same code on a different server, point the A record to this machine, and use it as a fallback server.&lt;/p&gt;

&lt;p&gt;As an early adopter of the latest technology, you have to live with few limitations; as I already mentioned, the dashboard experience needs to improve quite a bit — updating KV records and creating new tokens is not intuitive and buggy sometimes.&lt;/p&gt;

&lt;p&gt;Our bet on Workers seems to work well so far, it addresses all the limitations we faced with other solutions, and we are using this pattern for all our routing — handling webhooks, external integrations.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Did any of you try Workers yet? Please feel free to reach out to me (email) if you have any questions and ideas, I’ll be happy to take your feedback, help, and discuss it further.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Notes&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:fn-1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://workers.cloudflare.com/&quot;&gt;Cloudflare Workers&lt;/a&gt; &lt;a href=&quot;#fnref:fn-1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.cloudflare.com/en-gb/network/&quot;&gt;Cloudflare Network&lt;/a&gt; &lt;a href=&quot;#fnref:fn-2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://developers.cloudflare.com/workers/learning/how-workers-works&quot;&gt;How Workers Works&lt;/a&gt; &lt;a href=&quot;#fnref:fn-3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://blog.cloudflare.com/eliminating-cold-starts-with-cloudflare-workers/#:~:text=Unlike%20containers%2C%20Cloudflare%20Workers%20utilize,all%20%E2%80%93%20that&apos;s%20right%2C%20zero.&quot;&gt;Eliminating cold starts&lt;/a&gt; &lt;a href=&quot;#fnref:fn-4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://blog.cloudflare.com/introducing-cloudflare-workers/&quot;&gt;Introducing Cloudflare Workers&lt;/a&gt; &lt;a href=&quot;#fnref:fn-5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-6&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://developers.cloudflare.com/workers/platform/limits&quot;&gt;Worker Limits&lt;/a&gt; &lt;a href=&quot;#fnref:fn-6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-7&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://developers.cloudflare.com/workers/cli-wrangler&quot;&gt;Wrangler CLI&lt;/a&gt; &lt;a href=&quot;#fnref:fn-7&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-8&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://miniflare.dev/&quot;&gt;Miniflare&lt;/a&gt; &lt;a href=&quot;#fnref:fn-8&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-9&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://discord.com/invite/cloudflaredev&quot;&gt;Cloudflare Discord&lt;/a&gt; &lt;a href=&quot;#fnref:fn-9&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>What I&apos;m currently working on</title>
   
      <link href="https://twkrr.com/2021/09/27/currently-working-on/"/>
   
   <updated>2021-09-27T00:00:00-05:00</updated>
   <id>https://twkrr.com/2021/09/27/currently-working-on</id>
   <content type="html">&lt;p&gt;TLDR; World is recovering and taking a new shape. While it’s still unclear how it all ends, its impact will be transformative, and we are yet to understand it. While it’s all happening, we also started a new startup to help restaurants go online.&lt;/p&gt;

&lt;h2 id=&quot;world-is-recovering&quot;&gt;World is recovering&lt;/h2&gt;

&lt;p&gt;The past few months have been quite a ride for me, with a lot of mixed feelings and thoughts about how the world is recovering from the pandemic. The rise of new variants of the virus is not a good sign, but hopefully, with enough caution and everyone getting vaccinated, we’ll see the light and get back to everyday life – I can’t wait to travel back and be normal again.&lt;/p&gt;

&lt;h2 id=&quot;world-is-evolving&quot;&gt;World is evolving&lt;/h2&gt;

&lt;p&gt;While it’s still unclear how it all ends, the impact it is having on our lives and how it shapes our thinking of the future will be monumental. This increasingly digitized, asynchronous future was always inevitable, but we’re all forced into it in a concise amount of time. It feels obvious, but it’s also too early to take any of this for granted, people are still figuring it out, and I believe there’s no concrete idea of this future yet.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://twitter.com/paulg/status/1357450370793037826&quot;&gt;Paul Graham said it well&lt;/a&gt;;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“It can take decades to understand things you thought you understood as they were happening.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One other side effect that I think we’re not paying enough attention to is the increasing gap in education, wealth, and access to many other services.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.mckinsey.com/featured-insights/coronavirus-leading-through-the-crisis/charting-the-path-to-the-next-normal/the-covid-19-pandemic-is-widening-the-gap-between-leading-and-lagging-industries&quot;&gt;The COVID-19 pandemic is widening the gap between leading and lagging industries&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.weforum.org/agenda/2020/08/we-must-resist-covid-19-widening-us-education-gap/&quot;&gt;COVID-19 is widening the education gap. This is how we can stop it&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cnbc.com/2020/12/02/pandemic-widens-the-gap-between-the-haves-and-have-nots-report-finds.html&quot;&gt;42% of people falling behind as Covid-19 widens the wealth gap, report finds&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This striking gap is quite unsettling, and consequences are yet to be known.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;

&lt;h2 id=&quot;what-are-we-doing&quot;&gt;What are we doing?&lt;/h2&gt;

&lt;p&gt;Anyway, while this world is taking a different shape, I’m staying close to the F &amp;amp; B industry, especially in Southeast Asia. I worked for an F&amp;amp;B startup based in Singapore for about three years, building tools to run an online restaurant efficiently. During my long stint here, along with my colleagues, I’ve helped build a ton of tools for our online restaurant. We made tools that supported every aspect of the business – for the in-house sales team, delivery fleet, and customers themselves. Having these tools in place from the beginning helped us navigate COVID relatively safely.&lt;/p&gt;

&lt;p&gt;During the same period, we saw the other F&amp;amp;B owners struggle to adapt to the changes and operate with a lot of inefficiencies or sometimes close the business. It was sudden, and they were forced to find their way out with existing tools that were not ready to serve this event. We’ve seen medium-sized restaurants hack existing commerce solutions to sell the food online, noticed established fine dining restaurants go online through delivery platforms with exorbitant fees and brand dilution, and realized small size restaurants limited operations and sometimes temporarily closed the business especially, in Singapore a lot of hawkers.&lt;/p&gt;

&lt;p&gt;Though these things are always aware of, they become more apparent now and revealed how we solved most of these industry-specific problems in our past life. In a sense, we realized we had built tools for the restaurants of the future.&lt;/p&gt;

&lt;p&gt;Knowing some of these problems intimately, we started talking to many customers from the F&amp;amp;B to understand the difficulties and gaps more clearly. We identified few significant issues that they’re facing: branded food commerce, operations, integrations with platforms, and growth.&lt;/p&gt;

&lt;p&gt;Early this year, we decided to start Atlas the Shopify for restaurants in Southeast Asia with that hypothesis. Atlas is a platform that allows restaurants to accept orders through their branded website, aggregate orders from food delivery platforms, and also book their logistics.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;

&lt;h2 id=&quot;what-is-atlas&quot;&gt;What is Atlas?&lt;/h2&gt;

&lt;p&gt;Atlas is building the operating system for restaurants, focusing on Southeast Asia. Think Shopify for restaurants – the easiest way to start, run and grow any restaurant online and offline. The team at Atlas previously built Grain, a venture-backed online restaurant, to millions in revenue. Now, Atlas is building the software that helps restaurants achieve what Grain did in 3 years in less than 3 months. Currently just launched a v1 that is already helping restaurants save &amp;gt;50% of cost selling online. Atlas is looking to work with open-minded businesses to scale this up in closed beta. Existing customers include Odette, Poke Theory, Coconut Club, Amò and Providore.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;

&lt;h2 id=&quot;what-is-the-progress&quot;&gt;What is the progress?&lt;/h2&gt;

&lt;p&gt;We have spent the first months doing extensive planning, research, and designing the systems we are building up from scratch.&lt;/p&gt;

&lt;p&gt;Consolidating many inputs and feedback from customers during our initial conversations, we solved some high-level infrastructure challenges.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Multi-tenancy with isolated data&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;It was essential to ensure that all merchant data does not co-mingle with other tenants, and it mitigates any risks where data might end up in the wrong merchant’s account.&lt;/p&gt;

    &lt;p&gt;We have found a way to isolate all merchant data within their database, making it easier to extract and analyze. It will be much more friendly in the future when a merchant decides to invest in digital transformation and data-driven decision-making.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Blazing fast websites&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;We have decided to invest in Cloudflare’s Workers to deploy our consumer websites right at the edge of data centers. This means that not only will the websites be distributed to data centers all across the region; it also ensures that the website will be loaded from the closest data center to the consumer, drastically improving load times.&lt;/p&gt;

    &lt;p&gt;We’ve also split the cosmetic and data layers by intercepting requests and serving dynamic assets to different hosts but serving data through an optimized backend.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Highly scalable serverless infrastructure&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Serverless technologies have drastically optimized resource usage (compute), reducing costs. F&amp;amp;B business is a great use case to leverage technology like this — restaurants operate for a specific time during the day but can peak the traffic. We are using Google’s Cloud Run to power the backend to serve this use case; each merchant gets their group of servers that can autoscale depending on the traffic without any other merchants.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s been about four months since we started working. We’ve partnered with a few restaurant groups in Singapore and work closely with them to understand the problems more clearly and helping them go online. We have already launched few brands on the platform.&lt;/p&gt;

&lt;p&gt;Side note; we also graduated from YC (S21).&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;

&lt;h3 id=&quot;how-we-are-doing-it&quot;&gt;How we are doing it?&lt;/h3&gt;

&lt;p&gt;We are a small team, a group of 5 active folks working on this idea. We’re all based in Singapore and working closely to build a great product and business. I love this intimacy and collaboration – things move fast when we are small.&lt;/p&gt;

&lt;p&gt;And, here’s a quick glimpse of our tech stack.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Languages&lt;/em&gt;: Ruby, Javascript, Bash&lt;br /&gt;
&lt;em&gt;Frameworks (frontend)&lt;/em&gt;: React, React Native, Tailwind CSS&lt;br /&gt;
&lt;em&gt;Frameworks (backend)&lt;/em&gt;: Ruby on Rails, Node.js&lt;br /&gt;
&lt;em&gt;DevOps&lt;/em&gt;: Docker, Terraform, Google Cloud Platform, Cloudflare Workers, Firebase&lt;br /&gt;
&lt;em&gt;Databases&lt;/em&gt;: PostgreSQL, Workers KV&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;

&lt;h3 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h3&gt;

&lt;p&gt;We’re still in a pre-product market fit phase and excited to solve this problem.&lt;/p&gt;

&lt;p&gt;We’re actively onboarding more customers every week, enabling more restaurants to go online for the first time, and helping existing customers save costs.&lt;/p&gt;

&lt;p&gt;We firmly believe that the future of F&amp;amp;B doesn’t need to worry about distribution channels, logistics, or growth — they need to focus on things that matter (the food and customers!), and tools/technology must take care of the rest.&lt;/p&gt;

&lt;p&gt;If this sounds exciting, you can reach out to me for a chat or an opportunity to work or collaborate to build excellent tools for restaurant owners.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Frugality, liquidity, and holding position.</title>
   
      <link href="https://twkrr.com/2021/09/20/frugality-liquidity-holding-position/"/>
   
   <updated>2021-09-20T00:00:00-05:00</updated>
   <id>https://twkrr.com/2021/09/20/frugality-liquidity-holding-position</id>
   <content type="html">&lt;p&gt;&lt;em&gt;“Change breaks the brittle.” ― Jan Houtema&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Recent trends in the world that COVID influenced made me think deeply about the inadequacies in our communities. We are seeing people lose loved ones, many layoffs, dying/struggling businesses, broken health care systems, and travel restrictions.&lt;/p&gt;

&lt;p&gt;COVID, in a way, surfaced all the inefficiencies in our systems – pretty much everyone had to go into complete lockdown to figure out solutions while staying afloat during this crisis.&lt;/p&gt;

&lt;p&gt;This observation triggered my thoughts on preparedness for unanticipated incidents that have severe impacts on your life. I kept thinking about how companies, people, and other institutions with limited resources will survive this long haul without any revenue, cash flow, especially when they don’t have any reserves to stay afloat.&lt;/p&gt;

&lt;p&gt;We all heard that we should never let a good crisis go to waste, but how can we survive or stay afloat to figure something out of this crisis without having enough liquidity at our disposal? It gets complicated when you are running a business and people rely on you.&lt;/p&gt;

&lt;p&gt;The recent incidents made me realize that we consistently overestimate our position – in markets and personally. The truth is most of them are one or two events away from going back into hardship – one unanticipated crisis, and we have seen how the world just froze.&lt;/p&gt;

&lt;p&gt;The realization, in a way, scared me and made me reflect on my position and how I work, which led me to think about the consequences and how one can thrive beyond a crisis. In the process, I discovered three main components that help us stay in the game.&lt;/p&gt;

&lt;h3 id=&quot;frugality&quot;&gt;Frugality&lt;/h3&gt;

&lt;p&gt;Great things usually happen when you play a long-term game. Playing a game for a long time means you need to keep yourself ready to fight many unanticipated events – the best way to be prepared is to be frugal in life. Frugality not only prepares you for a bad day but in the event it occurs, you will know how to survive without much burn.&lt;/p&gt;

&lt;h3 id=&quot;liquidity&quot;&gt;Liquidity&lt;/h3&gt;

&lt;p&gt;It would be best if you kept iterating, experimenting, and improving yourself constantly and your business to find the right timing and make it influential. Sometimes it takes years, and sometimes it takes decades — having some form of liquidity to keep it going at random times gives you the advantage of being the first and freedom to go the extra mile.&lt;/p&gt;

&lt;h3 id=&quot;holding-position&quot;&gt;Holding position&lt;/h3&gt;

&lt;p&gt;It’s getting increasingly difficult to keep up with things these days; with so many distractions, everything looks attractive, and there’s little friction to take sides. But a deal gets real only when you commit to it and play it long enough — just like any position trade.&lt;/p&gt;

&lt;p&gt;You win the game by holding your position by committing to it without any distractions or digressions and stay long.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Find your battle, stay frugal, experiment more, hold your position and stay in the game long enough – and eventually, you’ll be right.&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Boredom, like pain, is a signal.</title>
   
      <link href="/2021/06/09/boredom/"/>
   
   <updated>2021-06-09T00:00:00-05:00</updated>
   <id>https://twkrr.com/2021/06/09/boredom</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;The most dangerous thing about carrying a cell phone everywhere is that you’re never bored. Boredom, like pain, is a signal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://twitter.com/paulg/status/1398920157964255236&quot;&gt;– PG on twitter&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I agree on a lot with PG here – being sensitive to those signals helped me a lot over the past and saved me from doing things I generally don’t enjoy.&lt;/p&gt;

&lt;p&gt;Ever since I read the tweet, I’ve been considering expanding it a bit further and stumbled upon Slava’s post today – it resembled my thoughts, and I’m going to leave it here for my reference.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;An important ingredient for doing the work is boredom. That’s how I got into programming. School was boring. We had three channels of television, and they were almost always boring. I had computer games, but I sucked at gaming and games quickly got frustrating. I read all the books that we had laying around. The only thing left was BASIC. So I started there and never stopped. The simple reason is that programming computers was the most interesting activity around.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;If boredom is a necessary ingredient, then portable internet is a disaster for doing the work. How are you supposed to get excited about anything if you’re never bored? I don’t know if I ever would have learned to program if I had modern internet. Why would I, if something more interesting was always a click away? This is true to this day. I can’t get anything done when I’m online. There is always something on the internet that’s locally more interesting or more important than writing the next paragraph, or threading a flag through a series of function calls, or reading a book. The only way I can get anything done is to turn the internet off.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://www.spakhm.com/p/productivity-advice&quot;&gt;– Productivity advice by Slava Akhmechet&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Container deployment on Google Cloud</title>
   
      <link href="https://twkrr.com/2021/01/17/containers-deployment-part-1/"/>
   
   <updated>2021-01-17T00:00:00-06:00</updated>
   <id>https://twkrr.com/2021/01/17/containers-deployment-part-1</id>
   <content type="html">&lt;p&gt;Earlier this month, I wrote a piece about how we started moving our operations to use containers on the Google cloud platform&lt;sup id=&quot;fnref:fn-1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. After reading the article, few friends got back to me with questions about how continuous deployments and orchestration work on the platform. I realized that I emphasized infrastructure choices and discussed implementation on a high note, which left them with the questions and me with an urge to document it.&lt;/p&gt;

&lt;p&gt;So here’s my attempt to demonstrate the inner workings of containers on the Google cloud platform. I’m breaking this down into two parts to discuss build, distribution and deployment separately.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;

&lt;h3 id=&quot;building-and-publishing-continuously-images&quot;&gt;Building and publishing (continuously) images&lt;/h3&gt;

&lt;p&gt;We used &lt;a href=&quot;https://cloud.google.com/sdk/docs/downloads-docker&quot;&gt;google/cloud-sdk&lt;/a&gt; to make it easy; it’s a docker image installed with Cloud SDK on Debian-based OS image. Depending on the configuration, we can trigger cloud build locally and/or on the CI tool.&lt;/p&gt;

&lt;p&gt;Cloud build can be triggered using: &lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gcloud builds submit &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &amp;lt;&lt;span class=&quot;nb&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/&amp;lt;project-name&amp;gt;/&amp;lt;image-name&amp;gt;:tag
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For the app, it looks something like this: &lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gcloud builds submit &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; gcr.io/awesome-project/awesome-app:v1.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command above will build images from the source (Dockerfile) and submit them to the container registry. Build logs will be available on the console for any debugging (Console &amp;gt; Cloud Build &amp;gt; History). All the images will be available in the container registry backed by cloud storage. A thing to take note of here is the container registry host; Google offers multiple hosts &lt;sup id=&quot;fnref:fn-2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, which specifies the location where you will store the images.&lt;/p&gt;

&lt;p&gt;Using cloud build is straightforward, but it has some limitations&lt;sup id=&quot;fnref:fn-3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; that are achievable with extra work. For instance, we can’t build an image with multiple tags using the CLI, we should use a configuration file (YAML)&lt;sup id=&quot;fnref:fn-4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; to define the multiple tags, and it can be dynamic.&lt;/p&gt;

&lt;p&gt;Here’s a simple configuration file that allows you to create an image with multiple tags — &lt;strong&gt;latest&lt;/strong&gt; and &lt;strong&gt;_COMMIT_ID&lt;/strong&gt;, which is dynamically derived.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;gcr.io/cloud-builders/docker&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Build&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;build&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-t&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;gcr.io/${_GOOGLE_PROJECT_ID}/${_APP_IMAGE_NAME}&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;gcr.io/cloud-builders/docker&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Tag&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;entrypoint&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/bin/bash&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-c&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;gcr.io/${_GOOGLE_PROJECT_ID}/${_APP_IMAGE_NAME}:latest&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;gcr.io/${_GOOGLE_PROJECT_ID}/${_APP_IMAGE_NAME}:${_COMMIT_ID}&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;substitutions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;_GOOGLE_PROJECT_ID&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;_GOOGLE_PROJECT_ID&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;_APP_IMAGE_NAME&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;_APP_IMAGE_NAME&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;_COMMIT_ID&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;_COMMIT_ID&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;gcr.io/${_GOOGLE_PROJECT_ID}/${_APP_IMAGE_NAME}&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Configuration and substitutions can be passed as arguments to the CLI command to generate images with multiple tags.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gcloud builds submit &lt;span class=&quot;nt&quot;&gt;--config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;cloudbuild.yml &lt;span class=&quot;nt&quot;&gt;--substitutions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_GOOGLE_PROJECT_ID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$GOOGLE_STAGING_PROJECT_ID&lt;/span&gt;,_APP_IMAGE_NAME&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$APP_IMAGE_NAME&lt;/span&gt;,_COMMIT_ID&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_COMMIT_ID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Suppose it feels like too much of a configuration. In that case, you can always configure docker to use gcloud by registering it as a docker credential helper&lt;sup id=&quot;fnref:fn-5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcloud auth configure-docker&lt;/code&gt; and continue using docker to publish images. It incurs some additional configuration on your CI, like setting up docker daemon and gcloud to build and publish images, but it can help us retain the implementation if we want to port the setup to any other platform.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;distributing-the-images&quot;&gt;Distributing the images&lt;/h3&gt;

&lt;p&gt;Google offers multiple solutions to deploy the containers — GKE, Cloud Run, and Container Optimized OS&lt;sup id=&quot;fnref:fn-6&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;We opted for container optimized OS as it was a safe bet for us and not to get locked into any one vendor/solution. It improves portability as we can replicate the setup on any system that supports docker runtime. Container optimized OS is not as powerful as your regular Linux distribution, it lacks a package manager but it’s light and secure.&lt;/p&gt;

&lt;p&gt;Our deployments are designed to leverage the instance templates feature on the Google platform. We create templates with app images and relevant tags during resource provisioning and use them to create new instances for distribution.&lt;/p&gt;

&lt;p&gt;Here’s how to create an instance template with an image and associated environment variables using gcloud CLI.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gcloud compute instance-templates create-with-container awesome-app-template &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--container-image&lt;/span&gt; gcr.io/awesome-project/awesome-app:v1.0.0  &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--machine-type&lt;/span&gt; n1-standard-2  &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--tags&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http-server&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--container-env&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;SECRET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ssssh &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--metadata&lt;/span&gt; startup-script&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;
    #! /bin/bash
    # Forward 80s traffic to 8000
    iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8000&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you’re using Terraform, you can use &lt;a href=&quot;https://github.com/terraform-google-modules/terraform-google-container-vm&quot;&gt;terraform-google-modules/terraform-google-container-vm&lt;/a&gt; to create an image and create a template with that module.&lt;/p&gt;

&lt;div class=&quot;language-hcl highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;gce-container&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;terraform-google-modules/container-vm/google&quot;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;~&amp;gt; 2.0&quot;&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;gcr.io/awesome-project/awesome-app:v1.0.0&quot;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SECRET&quot;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ssssh&quot;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;metadata_startup_script&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8000&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;resource&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;google_compute_instance_template&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;default&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;disk&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;source_image&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gce&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;source_image&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will create an instance template that can be used to provision VMs. A couple of things to take note of here;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Make sure the default compute service account has access to read images from the container registry&lt;/li&gt;
  &lt;li&gt;You have to write an IP table rule to map VMs ports to container ports&lt;sup id=&quot;fnref:fn-7&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-7&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;I’m sure there are many other ways to achieve the same outcome, and it all depends on the trade-offs we make to choose one. We currently run this setup to build and distribute our images; it allowed us to leverage the platform features while also designing a portable infrastructure.&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

&lt;p&gt;Please feel free to reach out to me (email) if you have any questions. I’ll be happy to take your feedback, help, and discuss it further.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Notes&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:fn-1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;/2021/01/05/docker-terraform-on-gcp/&quot;&gt;Our journey with Docker and Terraform on the Google cloud platform&lt;/a&gt; &lt;a href=&quot;#fnref:fn-1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://cloud.google.com/container-registry/docs/pushing-and-pulling &lt;a href=&quot;#fnref:fn-2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://github.com/GoogleContainerTools/kaniko/issues/217 &lt;a href=&quot;#fnref:fn-3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://cloud.google.com/cloud-build/docs/configuring-builds/create-basic-configuration &lt;a href=&quot;#fnref:fn-4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://cloud.google.com/sdk/gcloud/reference/auth/configure-docker &lt;a href=&quot;#fnref:fn-5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-6&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://www.youtube.com/watch?v=jh0fPT-AWwM &lt;a href=&quot;#fnref:fn-6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-7&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://cloud.google.com/compute/docs/containers/deploying-containers#limitations &lt;a href=&quot;#fnref:fn-7&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Our journey with Docker and Terraform on the Google cloud platform</title>
   
      <link href="https://twkrr.com/2021/01/05/docker-terraform-on-gcp/"/>
   
   <updated>2021-01-05T00:00:00-06:00</updated>
   <id>https://twkrr.com/2021/01/05/docker-terraform-on-gcp</id>
   <content type="html">&lt;p&gt;As an engineering team, we always operated with a modest infrastructure. We depended more on best practices to serve the business. Still, as we grew and projected the future, we understood the need to build site reliability engineering expertise to deliver reliable services.&lt;/p&gt;

&lt;p&gt;Lately, we have started building software for Grain’s Thailand market. It was relatively straightforward on the core business software, which allowed us to explore the infrastructure side of things. Starting fresh is always a unique opportunity to realize all the exciting things you’ve been researching, which are infeasible with legacy systems. Building software and especially the infrastructure for this new market felt like the one to us.&lt;/p&gt;

&lt;p&gt;We decided to adopt the relevant technologies and build for this new market with a more rigorous commitment. We had a good thought and goal; we decided to figure out an infrastructure that is simple enough to maintain without compromising security and scalability.&lt;/p&gt;

&lt;p&gt;Here’s how and what we did with it.&lt;/p&gt;

&lt;p&gt;Few more details before we start — we are a technology company based in Singapore working in the F&amp;amp;B industry. We run our backend on Ruby on Rails, and the front end includes a mix of Vue, React and React Native. We are entirely on the Google cloud platform using a range of computing and storage products.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;I’ll be essentially running you through this infrastructure image below and talk about a few difficulties we encountered along the way.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://twkrr.com/assets/infrastructure.jpeg&quot; /&gt;
  &lt;/figure&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;containers&quot;&gt;Containers&lt;/h2&gt;

&lt;p&gt;By now, we all have endured the benefits of containerizing the applications. I won’t repeat it and talk more about implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud build and Container Registry&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of using the actual docker daemon, we opted for &lt;a href=&quot;https://cloud.google.com/sdk/docs/downloads-docker&quot;&gt;google/cloud-sdk&lt;/a&gt; to get the job done as it suited well with the platform. Our CI/CD pipelines are on CircleCI.&lt;/p&gt;

&lt;p&gt;We used &lt;a href=&quot;https://cloud.google.com/sdk/gcloud/reference/builds/submit&quot;&gt;cloud build&lt;/a&gt; within the docker to build our images of our dockerized Ruby on Rails apps and publish them to the &lt;a href=&quot;https://cloud.google.com/container-registry/&quot;&gt;container registry&lt;/a&gt;. Images are stored in a storage bucket located in a region of our choice.&lt;/p&gt;

&lt;p&gt;Under the hood, cloud build uses &lt;a href=&quot;https://github.com/GoogleContainerTools/kaniko&quot;&gt;GoogleContainerTools/kaniko&lt;/a&gt; to build images. One of the gotchas was publishing an image with multiple tags&lt;sup id=&quot;fnref:fn-1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. We wanted to have multiple tags and found some difficulties in doing so, and we solved it by using a configuration file; it’s a simple YAML file that allows us to do a bit more.&lt;sup id=&quot;fnref:fn-2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to Rails’ secrets encryption feature, we didn’t have much difficulty managing secrets in our applications.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Container-Optimized VMs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of having a custom setup on a distro, we opted for &lt;a href=&quot;https://cloud.google.com/container-optimized-os&quot;&gt;container optimized VMs&lt;/a&gt;; these are lightweight VMs running customized OS preinstalled with docker and other monitoring tools. Easy to manage and maintain.&lt;/p&gt;

&lt;p&gt;There was no easy way to map VM’s ports to container ports&lt;sup id=&quot;fnref:fn-3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. We had to write an IP table rule as part of the startup script to achieve it.&lt;/p&gt;

&lt;p&gt;All the VMs are part of a managed instance group attached as a backend service to a load balancer with autoscaler, configured for our needs. All these resources, including the storage, are running in a custom VPC with fine-grained permissions&lt;/p&gt;

&lt;p&gt;We perform a rolling update action on the managed instance group to substitute existing VMs with new code with at least one active VMs to achieve zero downtime while continuously deploying code.&lt;sup id=&quot;fnref:fn-4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h2 id=&quot;infrastructure-as-code&quot;&gt;Infrastructure as code&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Terraform&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I must say, moving to Terraform one of the best decisions we have made. We’ve always maintained all our staging and production resources in a single project, and it got difficult to manage them over time. Thanks to Terraform, it helped us solve this problem; of course, it’s on top of all the benefits IaC tools provide.&lt;/p&gt;

&lt;p&gt;We now manage two different environments with Terraform; both these states are backed by google storage buckets of respective projects. We use separate variables and credentials files depending on the environment to provision the resources. We are planning to use workspaces&lt;sup id=&quot;fnref:fn-5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; to improve the process further.&lt;/p&gt;

&lt;p&gt;We used &lt;a href=&quot;https://github.com/terraform-google-modules/terraform-google-container-vm&quot;&gt;terraform-google-modules/terraform-google-container-vm&lt;/a&gt; to provision the VMs and developed custom modules for the rest of the resources. Life cycle blocks&lt;sup id=&quot;fnref:fn-6&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; came in pretty handy to circumvent panic when we were experimenting with the infrastructure.&lt;/p&gt;

&lt;h2 id=&quot;monitoring&quot;&gt;Monitoring&lt;/h2&gt;

&lt;p&gt;Monitoring is a necessary part of building reliable systems, and the right set of tools makes it easier for us to understand the system’s status. Google’s monitoring and logging system seemed like a good fit for us, mostly because of its more straightforward configuration for all the services.&lt;/p&gt;

&lt;p&gt;We have health checks in place and have a plan to add the pager rules to improve the whole recovery process shortly.&lt;/p&gt;

&lt;p&gt;We additionally started exploring tools like Grafana. Cloud Run&lt;sup id=&quot;fnref:fn-7&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-7&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; came in beneficial here; we run these pilot services on serverless infrastructure to lower costs and not incur any additional maintenance.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;It took us about four weeks to get all of this into some shape. I won’t say it was challenging, but we had fewer obstacles than we thought would arise along the process.&lt;/p&gt;

&lt;p&gt;Adopting these technologies has set us on a path to achieve the goals we have developed. Thanks to reliable tools, we are now more confident to solve the problems.&lt;/p&gt;

&lt;p&gt;We’re not done yet; we’ll be investing more time improving it, keeping an eye on the new technologies in this space, and exploring it further to build even more reliable systems. It’s exciting.&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
  . . .
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

&lt;p&gt;I led most of the development efforts and took the liberty to share them with you all. Please feel free to reach out to me (email) if you have any questions and ideas, I’ll be happy to take your feedback, help, and discuss it further.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Notes&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:fn-1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://github.com/GoogleContainerTools/kaniko/issues/217 &lt;a href=&quot;#fnref:fn-1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://cloud.google.com/cloud-build/docs/configuring-builds/create-basic-configuration &lt;a href=&quot;#fnref:fn-2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://cloud.google.com/compute/docs/containers/deploying-containers#limitations &lt;a href=&quot;#fnref:fn-3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://cloud.google.com/compute/docs/instance-groups/rolling-out-updates-to-managed-instance-groups &lt;a href=&quot;#fnref:fn-4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://www.terraform.io/docs/state/workspaces.html &lt;a href=&quot;#fnref:fn-5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-6&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://www.terraform.io/docs/configuration/meta-arguments/lifecycle.html &lt;a href=&quot;#fnref:fn-6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-7&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;https://cloud.google.com/run/ &lt;a href=&quot;#fnref:fn-7&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>If you can&apos;t travel far, travel deep: My year in review</title>
   
      <link href="https://twkrr.com/2020/12/31/year-in-review/"/>
   
   <updated>2020-12-31T00:00:00-06:00</updated>
   <id>https://twkrr.com/2020/12/31/year-in-review</id>
   <content type="html">&lt;p&gt;What an unfamiliar year it has been, once in a lifetime experience.&lt;/p&gt;

&lt;p&gt;When I started thinking about this year, my immediate feelings were all about how we got stuck at home with minimal exploration options and all the mental obstacles it provoked in the beginning. But with more reflection, I started realizing how it shaped me into handling unexpected change while still keeping me curious and enthusiastic about the things I relish.&lt;/p&gt;

&lt;p&gt;I started this year with a decent plan &lt;sup id=&quot;fnref:fn-1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; for work, travel, health, reading and other new areas I wanted to explore, but almost nothing went accordingly.&lt;/p&gt;

&lt;p&gt;Here’s what happened instead.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;lockdown-travel-diaries-almost&quot;&gt;Lockdown travel diaries (almost)&lt;/h2&gt;

&lt;p&gt;In March, I decided to make a short trip to Taiwan just as the COVID outbreak is developing worldwide. I must say it was a bold but equally exciting move to travel during these times, of course, with all the assurances.&lt;/p&gt;

&lt;p&gt;I usually find a lot of inspiration and joy in touring the west side, but the seasons have obliged me to look for a more realistic option this time around, and Taiwan looked like a great place to travel. In the end, it turns out to be one of my best trips; it was my non-solo trip, and it’s filled me with incredible experiences and memories. A friend of mine talks about it in more detail &lt;a href=&quot;https://nimmaakhilreddy.wordpress.com/2020/10/27/taipei-🇹🇼/&quot;&gt;here&lt;/a&gt; &lt;sup id=&quot;fnref:fn-2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;What made it worthwhile is that nearly every country went into lockdown, dropping all travel activities right after I came back from the trip. It’s the only significant travel I did this year.&lt;/p&gt;

&lt;h2 id=&quot;work-workout--from-home&quot;&gt;Work, workout … from home&lt;/h2&gt;

&lt;p&gt;In April (first week), Singapore announced a nationwide partial lockdown (circuit breaker), requiring many of us to work from home and to limit business operations for the next two months. Gyms, food places, and many outdoor activities were closed, which urged me to find alternative possibilities to fill my time with, like many of you. I picked up gaming, cooking and even ran about 100km (20 runs) while doing intermittent fasting in this course.&lt;/p&gt;

&lt;h2 id=&quot;more-love-for-computers&quot;&gt;More love for computers&lt;/h2&gt;

&lt;p&gt;In April (last week), Grain partnered with KOI &lt;sup id=&quot;fnref:fn-3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fn-3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, a local bubble tea brand, to deliver it across Singapore during the circuit breaker. I have reasonably good memories from this event.&lt;/p&gt;

&lt;p&gt;First, this partnership occurred suddenly, that we had limited time to make changes to our systems and infrastructure to support it. To our surprise, we organized and operated within constraints to get it up and running in a couple of days. We had tremendous traffic on the launch day, and our servers crashed. But we managed to get it up as soon as we could, and guess what we topped the app charts on both Singapore’s App Store and Play Store the next day, right along with giants like Zoom and Microsoft teams.&lt;/p&gt;

&lt;p&gt;This whole exercise got me deeply curious about infrastructure and site reliability leaving me uncomfortably excited for the rest of the year. So instead of sticking to the plan to learn TypeScript and Haskell, I dug deep into site reliability engineering and went on to help architect our new, more reliable, and highly secure infrastructure on Google Cloud Platform using tools like Docker, Terraform. In this process, I started learning much more about computers, magnifying my fondness for them.&lt;/p&gt;

&lt;h2 id=&quot;lost-habits&quot;&gt;Lost habits&lt;/h2&gt;

&lt;p&gt;I haven’t read as much as I would like to this year. I failed to carve out sufficient time for reading with so much excitement for site reliability engineering and other frequent digressions.&lt;/p&gt;

&lt;p&gt;Few good reads included &lt;a href=&quot;https://www.goodreads.com/book/show/41881472-the-psychology-of-money&quot;&gt;The Psychology of Money&lt;/a&gt;, &lt;a href=&quot;https://www.goodreads.com/book/show/37868583-the-prosperity-paradox&quot;&gt;The Prosperity Paradox&lt;/a&gt;, and &lt;a href=&quot;https://www.goodreads.com/book/show/35957157-thinking-in-bets&quot;&gt;Thinking in Bets&lt;/a&gt;.
I additionally enjoyed reading the interviews on &lt;a href=&quot;https://www.theobservereffect.org&quot;&gt;The Observer Effect&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I also discovered &lt;a href=&quot;https://open.spotify.com/show/2JXFCMLGVhTBtdz1WYxd4H?si=tbV2WQhJTHKF_cumIPA8eQ&quot;&gt;Mission ISRO with Harsha Bhogle&lt;/a&gt; podcast; it’s fantastic, and it led me to read biographies of Vikram Sarabhai and Homi Bhabha.&lt;/p&gt;

&lt;h2 id=&quot;back-to-startup-life&quot;&gt;Back to startup life&lt;/h2&gt;

&lt;p&gt;Many elements of the businesses we took for granted have proved us wrong this year; we’ve seen unusual things. Companies ran out of capital, people, and business ultimately. It’s even more relevant when you work in an F&amp;amp;B or travel industry where they have to shut the whole thing down or limit the operations for weeks to keep everyone safe. While this eliminated some business and use-cases, it also paved the way for new possibilities.&lt;/p&gt;

&lt;p&gt;We’re witnessing an extensive adaptation of digital technologies across industries. Working in the F&amp;amp;B sector, especially using technology, made me and my team realize the limitations for business owners to go digital with the current set of tools.&lt;/p&gt;

&lt;p&gt;So, towards the end of this year, we thought deeply about it and decided to take a stab at it and see if we can improve things. I started channeling all my focus and energy to solve this problem; we’re making adequate progress. Hopefully, we can bring some change overtime here.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;That’s it; these are some of the unexpected turns I’ve run into this year. If there’s anything, this year has forced me to look within and find opportunities. While it blocked every chance to travel far, it inspired me to travel deep into things that I already know.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
Thanks for reading, and happy new year. I’m looking forward to a safer and more pleasant year to come.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Notes&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:fn-1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Had to plan to travel every quarter, run a marathon, learn Haskell &lt;a href=&quot;#fnref:fn-1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://nimmaakhilreddy.wordpress.com/2020/10/27/taipei-🇹🇼/&quot;&gt;Taipei 🇹🇼&lt;/a&gt; &lt;a href=&quot;#fnref:fn-2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fn-3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://mothership.sg/2020/04/koi-grain-bubble-tea-delivery/&quot;&gt;KOI bubble tea now available for delivery in east S’pore, delivering to west side from May 5&lt;/a&gt; &lt;a href=&quot;#fnref:fn-3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Private Github Packages</title>
   
      <link href="https://twkrr.com/2020/08/01/private-github-packages/"/>
   
   <updated>2020-08-01T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/08/01/private-github-packages</id>
   <content type="html">&lt;p&gt;Over the past couple of weeks, I’ve been rewriting one of our internal apps, which we use to manage Grain’s order fulfillment. During this development, I’ve reused a lot of code and patterns that I’ve implemented in our customer-facing app earlier; it includes a lightweight promised based wrapper for fetch and other UI logic.&lt;/p&gt;

&lt;p&gt;Few days into the development, I started releasing the duplications and thought it would be fun to modularize the reusable code and publish it as modules. I had some experience doing something similar with npm, but this time I wanted to do it with Github packages, mainly because we’ve been considering to move all of our workflows to Github.&lt;/p&gt;

&lt;p&gt;Publishing code in public repositories as Github Packages is straightforward, and there are a ton of articles all over the internet to get us started. In our case, we wanted this to be in a private repository. To publish and consume the packages from private repositories wasn’t that obvious, and I haven’t found much documentation around it.&lt;/p&gt;

&lt;p&gt;It wasn’t that complicated to sort it out and get our first package running for consumption, but I had to hack around to get it working. It was fun figuring out stuff and thought to share it with you all here.&lt;/p&gt;

&lt;p&gt;Note: This guide assumes you already have code that is ready to be published and instructs you how to set up, distribute, and consume from Github Packages.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;publishing-a-package&quot;&gt;Publishing a package&lt;/h2&gt;

&lt;p&gt;Assuming you are in the root directory.&lt;/p&gt;

&lt;h3 id=&quot;update-npm-config&quot;&gt;Update npm config&lt;/h3&gt;

&lt;p&gt;From the documentation;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;npm gets its config settings from the command line, environment variables, and npmrc files&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this case, we’ll need to create (or update) the .npmrc file with registry details and enable access to the Github account.&lt;/p&gt;

&lt;p&gt;Your .npmrc file should look like this;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;//npm.pkg.github.com/:_authToken=$
registry=https://registry.yarnpkg.com/
@$:registry=https://npm.pkg.github.com
always-auth=true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token&quot;&gt;Follow this guide to create a personal access token on Github&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I’ve written a small &lt;a href=&quot;https://gist.github.com/surendharreddy/49ae79fb09df0365bcd0c6d2e6823af7&quot;&gt;script&lt;/a&gt; to get the job done. Execute the script with the right arguments to set up a config file with Github’s access token.&lt;/p&gt;

&lt;h3 id=&quot;publish-package&quot;&gt;Publish package&lt;/h3&gt;

&lt;p&gt;From here, it’s the same as publishing any module, do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm publish&lt;/code&gt;, and see it come alive with the right version on your GitHub repository.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;consuming-a-package&quot;&gt;Consuming a package&lt;/h2&gt;

&lt;p&gt;In your application, before installing the project dependencies, you need to repeat the npm config setup and update registry details and enable access to the Github account.&lt;/p&gt;

&lt;h3 id=&quot;update-npm-config-1&quot;&gt;Update npm config&lt;/h3&gt;

&lt;p&gt;It’s the same as what we did above, but this time, it’s in your application where you want to consume the package.&lt;/p&gt;

&lt;h3 id=&quot;install-package&quot;&gt;Install package&lt;/h3&gt;

&lt;p&gt;From here, it’s the same as installing any module, do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yarn add &amp;lt;package-name&amp;gt;&lt;/code&gt; (or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm install &amp;lt;package-name&amp;gt;&lt;/code&gt;) depending on your package manager. You might have to update the npmrc file with the right registry.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Now what?&lt;/p&gt;

&lt;h2 id=&quot;automate-the-setup-with-makefile&quot;&gt;Automate the setup with Makefile&lt;/h2&gt;

&lt;p&gt;If you have done it correctly, the above setup works on your machine, and you will have to make it work for the rest of the team if multiple team members are collaborating on the module or the application. The easiest way to onboard your team members to this idea is to create a Makefile and automate the setup, but you need the script I shared above to get it working.&lt;/p&gt;

&lt;p&gt;Here’s how the Makefile in our projects look;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;setup:
	@echo &lt;span class=&quot;s2&quot;&gt;&quot;Setting up registry&quot;&lt;/span&gt;
	sh ./setup_registry.sh &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;github-token&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, all your team members can get started by setting it up by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make github-token=$ setup&lt;/code&gt; in the root to start working on this package.&lt;/p&gt;

&lt;p&gt;This exercise allowed us to set up a process in place to privately host and publish reusable code as Github packages and consume them across projects and hope it helps you do the same in some way.&lt;/p&gt;

&lt;p&gt;Oh yeah, I found it challenging to find a boilerplate for the node Github package module. So, I created one with all the necessities. It’s on &lt;a href=&quot;https://github.com/surendharreddy/github-package&quot;&gt;Github&lt;/a&gt;, please feel free to use it.&lt;/p&gt;

&lt;p&gt;Let me know your thoughts and improvements to this setup, if any?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Forward refs in functional components</title>
   
      <link href="https://twkrr.com/2020/06/20/react-refs-hooks/"/>
   
   <updated>2020-06-20T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/06/20/react-refs-hooks</id>
   <content type="html">&lt;p&gt;First, this is a continuation of my &lt;a href=&quot;/react-refs&quot;&gt;previous post&lt;/a&gt; on understanding how forward refs work in React/React Native. The piece focuses on making sense of forwarding refs with hooks.&lt;/p&gt;

&lt;p&gt;The implementation of refs with hooks is similar to stateful component except that we a &lt;a href=&quot;https://reactjs.org/docs/hooks-reference.html#useref&quot;&gt;useRef&lt;/a&gt; hook to create a ref and attach it to the element. Below is a reasonably simple implementation of a simple list component.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FlatList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react-native&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SimpleList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;simpleList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;useRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FlatList&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;simpleList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the component, we can access methods such as scrollToEnd with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;simpleList.current.scrollToEnd(),&lt;/code&gt; and it’s the same for the rest.&lt;/p&gt;

&lt;p&gt;How it looks when the list is componentized? It’s again similar to the implementation that we do in stateful components.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FlatList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react-native&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AwesomeList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;forwardRef&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FlatList&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scrollsToTop&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bounces&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forwardRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forwardRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AwesomeList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;forwardRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We have a functional component with forwarding refs functionality.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FlatList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react-native&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AwesomeList&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./AwesomeList&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ListView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;listView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;useRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AwesomeList&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you might have guessed, we can now access child component methods using the forwarded ref, for example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listView.current.scrollToEnd()&lt;/code&gt; and so on. Sounds good?&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Oh wait, that’s not the end. Hooks also allow you to customize these methods that are exposed. Yes, it’s by using &lt;a href=&quot;https://reactjs.org/docs/hooks-reference.html#useimperativehandle&quot;&gt;useImperativeHandle&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From the documentation;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;useImperativeHandle customizes the instance value that is exposed to parent components when using ref. useImperativeHandle should be used with forwardRef.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How do we use it?&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;useImperativeHandle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FlatList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react-native&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AwesomeList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;forwardRef&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;simpleList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;useRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;useImperativeHandle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forwardRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;customScrollToEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;simpleList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;simpleList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scrollToEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FlatList&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scrollsToTop&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bounces&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;simpleList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forwardRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AwesomeList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;forwardRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the above example, we create a ref and attach it to the element and expose those methods using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;useImperativeHandle&lt;/code&gt; , and in this case, we are exposing the list’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scrollToEnd&lt;/code&gt; functionality as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;customScrollToEnd&lt;/code&gt; which can be triggered in the parent component with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listView.current.customScrollToEnd()&lt;/code&gt; method.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Making sense of forward refs</title>
   
      <link href="https://twkrr.com/2020/06/18/react-refs/"/>
   
   <updated>2020-06-18T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/06/18/react-refs</id>
   <content type="html">&lt;p&gt;I started my week with a bizarre UX bug, which I introduced in a recent refactor while I was componentizing a FlatList in a React Native project.&lt;/p&gt;

&lt;p&gt;The issue was I refactored one of the views, which was a typical FlatList wrapped in a ScrollView, which works like ViewPager. In the process, I lost all the refs related logic that I’ve composed earlier, which includes resetting the scroll position for specific data changes.&lt;/p&gt;

&lt;p&gt;Anyone who worked with React understands how refs provide a way to directly access DOM nodes or React elements created in the render method. This implementation is quite familiar while working with platform elements such as TextInput, ScrollView, or list views.&lt;/p&gt;

&lt;p&gt;Here’s how we do it in a simple FlatList.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FlatList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react-native&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SimpleList&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FlatList&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;simpleList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;
&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The ref here gives us access to component’s &lt;a href=&quot;https://reactnative.dev/docs/flatlist#methods&quot;&gt;methods&lt;/a&gt; to manage scroll. I mean, for example, you can scroll to the end of the list by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this.simpleList.scrollToIndex()&lt;/code&gt; and so on.&lt;/p&gt;

&lt;p&gt;It looks quite straightforward, right?&lt;/p&gt;

&lt;p&gt;But as I discussed earlier, I failed to retain this functionality when I componentized it, i.e., making this component reusable. This implementation makes SimpleList a child component, and in various cases, you can’t access the methods from a parent with the refs as we did first.&lt;/p&gt;

&lt;p&gt;So I started looking to get access to the refs in this reusable component and found a way that looked similar to prop drilling. We can get access by passing down the ref as one of the props to the child component, but the child component uses it differently. We forward this ref prop to the child component, and it’s methodically called ref forwarding.&lt;/p&gt;

&lt;p&gt;From &lt;a href=&quot;https://reactjs.org/docs/forwarding-refs.html#forwarding-refs-to-dom-components&quot;&gt;React documentation&lt;/a&gt;;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ref forwarding is a technique for automatically passing a ref through a component to one of its children. This is typically not necessary for most components in the application. However, it can be useful for some kinds of components, especially in reusable component libraries.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Great! How do we use it? Let’s see.&lt;/p&gt;

&lt;p&gt;We have our awesome list with a bunch of custom configurations, which can be used across the application without duplication (DRY).&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FlatList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react-native&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AwesomeList&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FlatList&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scrollsToTop&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bounces&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forwardRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Forwarding refs&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forwardRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AwesomeList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;forwardRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now the list is ready to accept refs as props. Let’s see how we can access it in a parent component.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react-native&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AwesomeList&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;./AwesomeList&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ListView&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;listView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;_scrollToIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scrollToIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AwesomeList&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the above example, we created a ref, using React’s createRef, and attached it to the element using ref, which is then forwarded to the child component. With this course, we enable access to child component methods and consume them but differently as declared in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_scrollToIndex&lt;/code&gt; function. Similarly, we can access all the other functionality of a child component using forward refs in React/React Native.&lt;/p&gt;

&lt;p&gt;Awesome, this solved my issue, but something else triggered my curiosity. How does this work with hooks? Let me explain that in the subsequent post.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Read more history, have more expectations and fewer forecasts.</title>
   
      <link href="https://twkrr.com/2020/06/16/history/"/>
   
   <updated>2020-06-16T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/06/16/history</id>
   <content type="html">&lt;p&gt;Forecasts only matter when conditions are constant from the moment we made them. Of course, you can have multiple models of the same thing, and one of them might accurately predict an event’s occurrence, but only if the conditions are constant.&lt;/p&gt;

&lt;p&gt;Life is brittle, and in most cases, we won’t be able to hold the constants and end up with unexpected results. That’s not the end; what we expect will happen, but not when we want it to happen, and we learn to pay attention to this from reading history.&lt;/p&gt;

&lt;p&gt;Read more history and when you do so as Morgan Housel said,&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;“…you become less surprised at whatever does happen, less confused about why it’s happening, and more confident about how people will react to it.”&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Digitalisation</title>
   
      <link href="https://twkrr.com/2020/06/14/digitalisation/"/>
   
   <updated>2020-06-14T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/06/14/digitalisation</id>
   <content type="html">&lt;p&gt;Earlier this week, I got my hands on Richard Hamming’s book, The art of doing science an engineering (published 1996). While reading, I came across this fascinating insight into the digitalisation of society.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Society is steadily moving from a material goods society to an information service society. At the time of the American Revolution, say 1780 or so, over 90% of the people were essentially farmers—now farmers are a very small percent of workers. Similarly, before WW-II most workers were in factories—now less than half are there. In 1993, there were more people in Government (excluding the military), than there were in manufacturing!&lt;/p&gt;

  &lt;p&gt;What will the situation be in 2020? As a guess I would say less than 25% of the people in the civilian work force will be handling things, the rest will be handling information in some form or other. In making a movie or a TV program you are making not so much a thing, though of course it does have a material form, as you are organising information. Information is, of course, stored in a material form, say a book (the essence of a book is information), but information is not a material good to be consumed like food, a house, clothes, an automobile, or an airplane ride for transportation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;The insight got me thinking, and made me ask; &lt;strong&gt;what other material goods that are in the form of information are not entirely digitised?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To which the answer I had then was; meetings, education, health (workouts, yoga) and recreational activities. Most of these are already digitised to some extent, but not entirely until recently.&lt;/p&gt;

&lt;p&gt;I mean, the COVID-19 has required a lot of activities to be conducted online. The analysts in a recent &lt;a href=&quot;https://www.mckinsey.com/business-functions/mckinsey-digital/our-insights/the-covid-19-recovery-will-be-digital-a-plan-for-the-first-90-days&quot;&gt;McKinsey report&lt;/a&gt; declared that;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We are witnessing what will surely be remembered as a historic deployment of remote work and digital access to services across every domain.&lt;/p&gt;

  &lt;p&gt;Indeed recent data show that we have vaulted five years forward in consumer and business digital adoption in a matter of around eight weeks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s almost been three months or more depending on where you stay since we got into these unusual times, and there’s no easy escape from it, at least not until we figure out a vaccine. If we are going to live with it, many firms have to change the way they manage the business, and it looks like conducting them online is the only way out and is confirmed.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;br /&gt;
If you don’t, the incidents usually will force you to do so. Which is why I think we’ll see an even more digitalisation of businesses going forward and here’s why I believe COVID-19 is going to influence some of these decisions.&lt;/p&gt;

&lt;h3 id=&quot;physical-space&quot;&gt;Physical space&lt;/h3&gt;
&lt;p&gt;In the best-case scenario, it seems we might take at least a year or more to find a proper vaccine to diagnose the COVID virus fully. Until then, one of the only proven strategies to be away from this virus is by practicing social distancing. It’s already a mandatory rule in many countries.&lt;/p&gt;

&lt;p&gt;In that case;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Compliance with social-distancing measures seem likely to require more space per worker for many months. That will give companies a reason to encourage some workers to stay away some or all of the time while not changing the demand for office space much.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://www.economist.com/briefing/2020/06/11/covid-19-challenges-new-yorks-future&quot;&gt;Centres of excellence - Covid-19 challenges New York’s future&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With more space per worker in the office, it forces the rest to work from home, and the only way to keep everyone connected and run business is by digitising processes. We can expect more firms to go remote to some extent and create innovative ways to conduct business activities digitally.&lt;/p&gt;

&lt;h3 id=&quot;behaviour&quot;&gt;Behaviour&lt;/h3&gt;
&lt;blockquote&gt;
  &lt;p&gt;“In a moment of crisis, minds too can change quickly. You can have bitter arguments with your siblings for years, but when some emergency occurs, you suddenly discover a hidden reservoir of trust and amity, and you rush to help one another.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://www.ft.com/content/19d90308-6858-11ea-a3c9-1fe6fedcca75&quot;&gt;Yuval Noah Harari: the world after coronavirus&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To my knowledge, I think COVID-19 is the only catastrophic event that has impacted everyone on this small planet equally since the birth of the internet. Almost every country had a positive case and went into lockdown.&lt;/p&gt;

&lt;p&gt;Everyone has a certain degree of empathy towards the pain it can cause and are ready to try new habits that can keep them safer, including those they always refused. This mindset anchors a suitable environment to scale ideas that work in specific geographies and domains. It’s why everyone can make sense of remote work, online education,  and eCommerce these days.&lt;/p&gt;

&lt;p&gt;We’ve seen a lot of developing nations and some old businesses adapt to these new forms of work, education, and commerce, and failed to keep up with it for different reasons, but not anymore because it’s the only way you can be involved and be safe.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;br /&gt;
Who knows it might end up being the new norm by the time we figure out a vaccine in a year and see a lot of business activity happening on the internet than the material world. If it does, it changes the dynamics of the world and instantly puts your talent on a global marketplace, and you’ll compete with everyone.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>India and Sachin Tendulkar</title>
   
      <link href="https://twkrr.com/2020/06/07/india-and-sachin/"/>
   
   <updated>2020-06-07T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/06/07/india-and-sachin</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://www.espncricinfo.com/story/_/id/22453145/tendulkar-country&quot;&gt;In Tendulkar country&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;His international debut came a year before India opened up its economy. His rise mirrored India’s early-90s rise, when foreign corporations arrived in India for the first time, accounts swelling with advertising dollars, looking around for a face. They found Sachin.&lt;/p&gt;

  &lt;p&gt;He was India’s first modern sports star, a combination of Babe Ruth, Muhammad Ali and Michael Jordan, because his rise mirrored a nation’s economic rise, and he forever changed sports celebrity and marketing in India. Once, when an American company executive contacted his agent and wanted to understand what place Sachin held in Indian culture, the agent didn’t quote the number of Test wins, or international centuries. He said, simply, that Sachin endorsed Audemars Piguet watches, and that the company made a model just for him. The executive was sold.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;He not only mirrored the economic rise in India, but he has also risen the aspirations of 90s grown kids. He was an inspiration to many.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Tech company</title>
   
      <link href="https://twkrr.com/2020/06/01/tech-company/"/>
   
   <updated>2020-06-01T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/06/01/tech-company</id>
   <content type="html">&lt;p&gt;Most analysts usually talk about the business side of things when discussing tech companies and hardly glance at the tech. They indeed have fascinating insights about the tech companies, and I always genuinely enjoyed knowing them. I use them in my models when thinking about technology. But, as an engineer, I always thought that these investigations are missing &lt;strong&gt;how&lt;/strong&gt; part of technology. It’s not that they don’t want to talk about it, but I assume most of them are not sufficiently informed.&lt;/p&gt;

&lt;p&gt;This missing piece in tech analysis always kept me awake, and  I had jotted down some opinions to share it someday and what’s the best time than now.&lt;/p&gt;

&lt;p&gt;So what is a tech company?&lt;/p&gt;

&lt;p&gt;It’s clear from the business that a tech company has zero marginal cost, zero transactional costs, and has limitless upside, of course, with a hefty upfront fee.&lt;/p&gt;

&lt;p&gt;Ben Thompson is his popular article &lt;a href=&quot;https://stratechery.com/2019/what-is-a-tech-company/&quot;&gt;What is a tech company&lt;/a&gt; demonstrates that very accurately;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Software creates ecosystems.&lt;br /&gt;
Software has zero marginal costs.&lt;br /&gt;
Software improves over time.&lt;br /&gt;
Software offers infinite leverage.&lt;br /&gt;
Software enables zero transaction costs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I agree with most of it, and how can we materialize a piece of code into something that can embody these characteristics.&lt;/p&gt;

&lt;p&gt;In very well known computer science book “Structure and Interpretation of Computer Programs,” computational processes are described as;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“… abstract beings that inhabit computers. As they evolve, processes manipulate other abstract things called data. The evolution of a process is directed by a pattern of rules called a program. People create programs to direct processes.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Drawing analogies from this very standard reference, the software is nothing but data and rules. It’s not your website, mobile app, etc. To understand it better, let’s apply the inversion model; you’re not a tech company if you have a website or a mobile app.&lt;/p&gt;

&lt;p&gt;Let’s dig into it.&lt;/p&gt;

&lt;h3 id=&quot;channel-agnostic-systems&quot;&gt;Channel agnostic systems&lt;/h3&gt;
&lt;p&gt;Most of the software, in essence, is some UI (channel) in the form of a website, mobile app, wearable, or an AR/VR layered over a very well-defined data models and relations that are highly specific to the business.&lt;/p&gt;

&lt;p&gt;If you think about it, the real technology here is the relations and models you build with data that is highly specific to the business. These models and relationships are often agnostic to the channel. Of course, to begin with, you need to pick one channel, but that’s not the end.&lt;/p&gt;

&lt;p&gt;The fact is, these channels are always changing; since the inception of cloud computing, which made the internet more powerful and useful, we transitioned from using PCs to mobile to wearables and heading towards AR/VR. A tech company develops data and designs relations and models to be accessible over any channel with minimal changes.&lt;/p&gt;

&lt;h3 id=&quot;integrations&quot;&gt;Integrations&lt;/h3&gt;
&lt;p&gt;Once you design your tech in that way accessible over any channel with minimal changes, you can spend all your time and resources in making it available to more people on diverse channels. The faster, the better, moving more quickly gives you the first-mover of the value advantage, and in the process, sometimes you get to set the industry standards and ride on the trends.&lt;/p&gt;

&lt;p&gt;Integrations come in to play to enable this speed and growth. With minimal changes, you can confidently promise a consistent behavior, which encourages a lot of small players to rely upon you. It allows everyone to participate positively and partner with you. Remember, partnerships are better than the competition; it’s easy too.&lt;/p&gt;

&lt;h3 id=&quot;modeling-and-forecasting&quot;&gt;Modeling and forecasting&lt;/h3&gt;
&lt;p&gt;As the system gets used a lot, you observe various behaviors and processes tagged to a specific collection of users. This database of users with particular behavior unveils new opportunities to explore.&lt;/p&gt;

&lt;p&gt;Exploration is non-deterministic; in most cases, it’s not cheap, and sometimes it’s irreversible. Technology makes it less expensive and comfortable.&lt;/p&gt;

&lt;p&gt;The software allows you to model or represent some aspect of the real world with existing data and forecast different versions of it to get different vantage points, which makes exploration cheaper and more fun; the only limitation is your ability to imagine.&lt;/p&gt;

&lt;h3 id=&quot;process-automation&quot;&gt;Process automation&lt;/h3&gt;
&lt;p&gt;It’s a very well known fact that the repeated exhibition of core competencies is a result of the processification of decision making. In an ever-evolving business, teams grow, responsibility shrinks, and the ownership fades away, and it dilutes this knowledge of the process.&lt;/p&gt;

&lt;p&gt;Throughout history, we’ve seen events that adequately proved that process knowledge deteriorates over time and every business that relied on people to master these processes faded.&lt;/p&gt;

&lt;p&gt;But in a tech company, along with systemizing decision making, the information we use is represented in a digital form. Ultimately, this allows us to automate the process itself as long as the shape of the input is uniform. The best part of this automation? It will enable us to fail fast, cheaply, and improve.&lt;/p&gt;

&lt;p&gt;Once this is in place, you are ready to work on strategies that can leverage network-effects and have innovative business models to accomplish increasing returns and that’s what makes you a tech company.&lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;
That being said, this always starts with a business goal, a vision larger than life, and then we all work backward to accomplish it.  You don’t look for problems that your marvelous technology can solve, your technology is a solution to the problems that already exist to which people want a solution and cannot resolve it on their own.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Databases 101</title>
   
      <link href="https://twkrr.com/2020/05/29/databases-101/"/>
   
   <updated>2020-05-29T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/05/29/databases-101</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;“Computational processes are abstract beings that inhabit computers. As they evolve, processes manipulate other abstract things called data. The evolution of a process is directed by a pattern of rules called a program. People create programs to direct processes.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I came across this profound description of a computational process in SICP, which substantially changed how I think about programming. It simplified programming into two essential things, data, and rules: no languages, no frameworks. I’m already aware of the rules, and the data side of things is something I became curious about ever since.&lt;/p&gt;

&lt;p&gt;I followed my curiosity and discovered many things. I came across tools and techniques that helped me think clearly with a data-first approach. As time passed, I started realizing that most of the software, in essence, is some sort of UI in the form of a website, mobile app, wearable, or an AR/VR layered over a very well-defined data models that are highly specific to the business. That realization blew my mind; I couldn’t stop thinking about data models and relations. I had to respond to this calling immediately, and that’s how I ended up here with an urge to learn everything about databases.&lt;/p&gt;

&lt;p&gt;I’m relatively new to databases; I needed to learn things from the ground up. So, I researched quite a bit, found some fantastic resources online, and spent some time learning. I thought of writing about all my learnings’ to clarify my understanding and here are my reading notes;&lt;/p&gt;

&lt;h2 id=&quot;databases-and-management-systems&quot;&gt;Databases and management systems&lt;/h2&gt;

&lt;p&gt;A database is the model representation of some aspect of the real world. A database management system (DBMS) is a tool that allows end-users to interact with this data to organize, store, and analyze.&lt;/p&gt;

&lt;h2 id=&quot;file-based-system&quot;&gt;File-based system&lt;/h2&gt;

&lt;p&gt;The most straightforward implementation of a database is a flat-file (e.g., a .csv file), and we can use any programming language as DBMS to read this record and analyze it. They are known as filed-based systems.&lt;/p&gt;

&lt;p&gt;It worked, but it is incompetent for different reasons;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Well, it’s slow. (When you think of billions of records)&lt;/li&gt;
  &lt;li&gt;Data Integrity
    &lt;ul&gt;
      &lt;li&gt;How do we ensure there are no duplicates?&lt;/li&gt;
      &lt;li&gt;How do we ensure we are using proper data types during manipulation? (E.g., Update a string type with a
 and vice versa)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Implementation
    &lt;ul&gt;
      &lt;li&gt;What if we want another application to use this file?&lt;/li&gt;
      &lt;li&gt;What if two threads try to write to the same file?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Durability
    &lt;ul&gt;
      &lt;li&gt;What happens to our data if an application crashes?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach is not sophisticated, and it’s expensive.&lt;/p&gt;

&lt;p&gt;To overcome this, many organizations, computer engineers came up with different designs of DBMSs. But these initial DBMSs were challenging to build and manage. Tightly coupled physical and logic layers made it painful to write and maintain databases because you have to tell the system how to store information as a specific type in a database and build logic.&lt;/p&gt;

&lt;p&gt;E.g., If you store a piece of data as a tree structure, or as a hash table in your database. You have to use different types of queries (APIs) to handle it, depending on the model.&lt;/p&gt;

&lt;p&gt;Programmers need to rewrite the database management system every time there is a significant change in application-related data.&lt;/p&gt;

&lt;p&gt;Sounds unproductive, right? Welcome to relational databases; Thanks, Codd. He got baffled by all these rewrites at IBM and decided to solve this problem.&lt;/p&gt;

&lt;h2 id=&quot;relational-databases&quot;&gt;Relational databases&lt;/h2&gt;

&lt;p&gt;So, Ted Codd came up with a theory to abstract things and avoided rewrites and maintenance. He inscribed some of the great ideas in this paper &lt;a href=&quot;https://www.seas.upenn.edu/~zives/03f/cis550/codd.pdf&quot;&gt;A Relational Model of Data for Large Shared Data Banks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In his theory, he suggests;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Store database in simple data structures&lt;/li&gt;
  &lt;li&gt;Access data through a high-level language&lt;/li&gt;
  &lt;li&gt;Leave physical storage to implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To abstract things like this we have to understand two important concepts;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Data model — It is a collection of concepts for describing the data in a database. E.g., Relational, Key/Value, Document&lt;/li&gt;
  &lt;li&gt;Schema — It is a description of a particular group of data using a given data model.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This theory helped people build relational databases that solved all the issues faced earlier;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Structure — Definition of relations&lt;/li&gt;
  &lt;li&gt;Integrity — Constraints&lt;/li&gt;
  &lt;li&gt;Manipulation — Access and modify&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In relational databases, DBMS tools will take care of implementation and storage, end-users will manipulate it using different languages.&lt;/p&gt;

&lt;p&gt;We can manipulate a relational database using two different data types of languages;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Procedural&lt;/strong&gt;; The query specifies the (high-level) strategy the DBMS should use to find the desired result (Relational algebra)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Non-Procedural&lt;/strong&gt;; The query specifies only what data is wanted and not how to find it (Relational calculus)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both these manipulation languages use relational algebra to manipulate data.&lt;/p&gt;

&lt;p&gt;In a relational database, there are only two essential elements; Relations and Tuples. They are the building blocks for storage and retrieval.&lt;/p&gt;

&lt;h2 id=&quot;sql&quot;&gt;SQL&lt;/h2&gt;

&lt;p&gt;SQL is a query language for data manipulation. It implements relational algebra or relational calculus.&lt;/p&gt;

&lt;p&gt;SQL is not a single language, but it’s a collection of multiple things;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Data Manipulation Language (DML) is a collection of things that manipulate data. E.g., statements; INSERT, UPDATE, SELECT.&lt;/li&gt;
  &lt;li&gt;Data Definition Language (DDL) is used to create and modify database objects such as tables and indexes. E.g., statements; CREATE, DROP.&lt;/li&gt;
  &lt;li&gt;Data Control Language (DCL) is used to define control access to data stored in a database. E.g., statements; GRANT, REVOKE.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it for now; this is a broad introduction to databases. I will cover more, especially the operations in databases and query languages in my next post.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Disrupting beliefs</title>
   
      <link href="https://twkrr.com/2020/05/28/disrupting-beliefs/"/>
   
   <updated>2020-05-28T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/05/28/disrupting-beliefs</id>
   <content type="html">&lt;p&gt;To build products or services that last, we need to develop a new belief system (a new kind of truth) or reframe the existing ones’ that fundamentally change how we think about specific things in life.&lt;/p&gt;

&lt;p&gt;Some stories from the past to understand how it worked for some well-known organizations,
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Ford&lt;/strong&gt; convinced that people need cars to travel faster and built an innovative manufacturing technique (assembly line) to deliver as many cars as possible in a short period. 
&lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Apple&lt;/strong&gt; convinced that people could be creative with internet-enabled devices and created a suite of products to get them started. 
&lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Amazon&lt;/strong&gt; convinced people that they could buy things online and built an excellent operations mechanism to fulfill orders with efficiency and speed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If not, we are building solutions on existing belief systems, which means we’re merely competing and not creating any difference.&lt;/p&gt;

&lt;p&gt;Relying on an existing belief system works if you undoubtedly know that enough people don’t have access to it. In this case, your job is not to reinvent the wheel but to make it accessible to as many people as you can before the competition begins.&lt;/p&gt;

&lt;p&gt;But creating a new belief system eliminates all the competition and gives you a first and a last mover of the value advantage. It’s not easy or straightforward to build a new belief system. To do so, it’s a must to understand (w.r.t first principles) market dynamics, trends, customer behaviors, and belief systems that already exist and respond invariably.&lt;/p&gt;

&lt;p&gt;This thought process, I believe, will naturally make you good at building products and services that last long and have a significant impact. At some point, they make you feel like it’s impossible to function without them (just like the internet, mobiles, cars, etc.)&lt;/p&gt;

&lt;p&gt;Creating a belief system like this also changes how we think about the stakeholders of the business. For example, when working on a new belief system,&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The marketing teams&lt;/strong&gt;’ job is to help people discover this new belief system.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The sales teams’&lt;/strong&gt; job is to educate people about this new belief system.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The product teams’&lt;/strong&gt; job is to give people the tools to navigate through this new belief system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bottom line is, you can be successful either way, with or without disrupting beliefs. However, you can only avoid competition, uncertainty by building something new or by giving a new meaning to something that already exits. You should be passionate about the change in both cases, and as William Pollard said, “Those who initiate change will have a better opportunity to manage the change that is inevitable.”&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Being right, big time in a big way.</title>
   
      <link href="https://twkrr.com/2020/05/24/right/"/>
   
   <updated>2020-05-24T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/05/24/right</id>
   <content type="html">&lt;p&gt;While I was reading my daily &lt;a href=&quot;https://stratechery.com&quot;&gt;Stratechery&lt;/a&gt; update today, I came across this fascinating story about OpenDoc. In the article, I discovered an exceptional &lt;a href=&quot;https://www.youtube.com/watch?v=yQ16_YxLbB8&quot;&gt;question-and-answer session&lt;/a&gt; that Steve Jobs held with developers in 1997, just months after Apple had acquired Next.&lt;/p&gt;

&lt;p&gt;In the session, towards the end, a developer inquires about OpenDoc&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Mr. Jobs, you’re a bright and influential man. It’s sad and clear that on several counts you’ve discussed, you don’t know what you’re talking about. I would like, for example, for you to express in clear terms how, say, Java and any of its incarnations addresses the ideas embodied in OpenDoc. And when you’re finished with that, perhaps you can tell us what you personally have been doing for the last seven years.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;To which Jobs responds,&lt;/p&gt;
&lt;blockquote&gt;

  &lt;p&gt;You know, you can please some of the people some of the time, but…&lt;/p&gt;

  &lt;p&gt;One of the hardest things when you’re trying to effect change is that people like this gentleman are right in some areas.&lt;/p&gt;

  &lt;p&gt;I’m sure that there are some things OpenDoc does — probably even more than I’m not familiar with — that nothing else out there does. I’m sure that you can make some demos, maybe a small commercial app, that demonstrates those things. The hardest thing is how does that fit into a cohesive larger vision that’s going to allow you to sell eight billion dollars or ten billion dollars of product a year?&lt;/p&gt;

  &lt;p&gt;One of the things I’ve always found is that you’ve got to start with the customer experience and work backwards to the technology. You can’t start with the technology and try to figure out where you’re going to try to sell it. I’ve made this mistake probably more than anybody else in this room and I’ve got the scar tissue to prove it and I know that it’s the case. As we have tried to come up with a strategy and a vision for Apple, it started with what incredible benefits can we give to the customer? Where can we take the customer? Not starting with, “Let’s sit down with the engineers and and figure out what awesome technology we have and then how are we going to market that”, and I think that’s the right path to take.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The most interesting insight for me from this answer was how being right some times in some areas is wrong in the long term.&lt;/p&gt;

&lt;p&gt;What I mean is, in the short term (in business), any solution that gives a bit of relief (money and time-wise) sounds like a good thing. While it is good to find these solutions that are hacks once in a while and hold on to it, it should not end up being our lifestyle, especially the ones that stop us from exploring the bigger picture and growing.&lt;/p&gt;

&lt;p&gt;If it ends up being our lifestyle, we start encouraging ideas, solutions that sound correct for that moment, and never think beyond it, and this silos our thinking. It’s okay if we are happy with it. Otherwise, we have to change how we feel about it.&lt;/p&gt;

&lt;p&gt;If we want to be successful in most cases, it’s not about being right, but it’s about being right big time in a big way. It doesn’t necessarily mean we always have to work on solutions that solve more significant problems, but even the small issues we choose to work on have to connect to something big.&lt;/p&gt;

&lt;p&gt;I think Michael J. Mauboussin summarized it well, “Focus not on the frequency of correctness, but the magnitude of correctness.”&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>The COVID opportunity</title>
   
      <link href="https://twkrr.com/2020/05/21/the-covid-opportunity/"/>
   
   <updated>2020-05-21T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/05/21/the-covid-opportunity</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://www.fool.com/earnings/call-transcripts/2020/04/30/amazoncom-inc-amzn-q1-2020-earnings-call-transcrip.aspx&quot;&gt;Brian T. Olsavsky in Amazon earnings call&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;We are heavily constrained, again it’s an odd quarter because generally the biggest uncertainty we have this customer demand, and with the order and how much of it they’ll order. Demand has been strong, the biggest questions we have in Q2 are more about ability to service that demand and that is the products that people are ordering in a full way, not blocking or making it hard to find non-essential items, increasing marketing, and everything else.&lt;/p&gt;

  &lt;p&gt;So I think the challenge is really on everything besides the top line. And top line is certainly not to be taken for granted. There’s always the importance of having attractive offerings in stock for customers. But usually things you can count on, the cost structure, the ability to get products, yes, your capacity for shipping and delivering, those are usually things that you can take for granted, and in this quarter, you can’t. That’s really where the uncertainty is driven.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think this applies to every business that is experiencing tremendous growth during this pandemic. Almost all the essential businesses, especially food and grocery delivery startups, are running at their full capacity to cope with the demand. But as Dave said this demand and growth are uncertain.&lt;/p&gt;

&lt;p&gt;What sticks after this pandemic is how people experienced your service (reliability) and product (quality). It’s a great opportunity if businesses start using this uncertain growth to improve that customer experience. It’s rare to see growth like this and any business which is not constantly experimenting to improve things is definitely missing out big time or will soon.&lt;/p&gt;

&lt;p&gt;If we think about it, all these essentials are not really price-sensitive and the only differentiator is the reliability of service. This makes it easy for customers to shift to another service when things are bad. The only job of any business now is to make sure customers are not thinking about it.&lt;/p&gt;

&lt;p&gt;EDIT: [May 27, 2020] Updated earnings call source link.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Compounding</title>
   
      <link href="https://twkrr.com/2020/05/17/compounding/"/>
   
   <updated>2020-05-17T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/05/17/compounding</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Chetty thinks about revolution like an economist does: as a compounding accumulation of marginal changes. Bump the interest rate on your savings account by one notch, and 30 years later, your balance is much improved. Move a family to a better zip code, or foster the right conditions in that family’s current neighborhood, and their children will do better; do that a thousand times, or ten thousand, and the American dream can be more possible, for more people, than it is today.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is from &lt;a href=&quot;https://www.theatlantic.com/magazine/archive/2019/08/raj-chettys-american-dream/592804/&quot;&gt;Raj Chetty’s American Dream&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the returns in life whether good or bad come from these small marginal changes we accumulate over time. This is not new although I never thought of it in the context of the place we choose to stay and its neighbourhood.&lt;/p&gt;

&lt;p&gt;However, it is also important to remember that, it is not if we have made any of it but most of the times it is all about how we preserve and use it.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Optimism</title>
   
      <link href="https://twkrr.com/2020/05/03/optimism/"/>
   
   <updated>2020-05-03T00:00:00-05:00</updated>
   <id>https://twkrr.com/2020/05/03/optimism</id>
   <content type="html">&lt;p&gt;Mark Zuckerberg in &lt;em&gt;&lt;a href=&quot;https://www.fool.com/earnings/call-transcripts/2020/04/29/facebook-inc-fb-q1-2020-earnings-call-transcript.aspx&quot;&gt;Facebook Inc (FB) Q1 2020 Earnings Call&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I have always believed that in times of economic downturn, the right thing to do is to keep investing in building the future, and I believe this for a few reasons. First, when the world changes quickly, people have new needs and that means that there are more new segments to build. Second, since many big companies will pull back on their investments, there are a lot of things that wouldn’t otherwise get built, but that we can help deliver. And the third, I believe that there is a sense of responsibility and duty to invest in the economic recovery and to provide stability for your community and stakeholders if you have the ability to do so. And we’re in a fortunate position to be able to do this. Along with our strong financial position and the important social value our services provide, we’re planning to hire at least 10,000 more people in product and engineering roles this year, so we can continue building and making progress.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is so much despair in the world now, and it is challenging to understand what people are going through during these tough times. Fortunately, not everyone (hopefully) are dealing with this, especially some of the tech companies (entertainment, social, essential services). If you are one of them, please keep building tools at your capacity to help humanity get through these times.&lt;/p&gt;

&lt;p&gt;I believe this is a great time and opportunity to show how the right technology solutions can be helpful.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>2019 in review</title>
   
      <link href="https://twkrr.com/2019/12/29/year-in-review/"/>
   
   <updated>2019-12-29T00:00:00-06:00</updated>
   <id>https://twkrr.com/2019/12/29/year-in-review</id>
   <content type="html">&lt;p&gt;A lot of things I did over this year looked more like a starting point to something, something that is getting stable and something that can become big and personal. When I thought or was asked to review this year, I thought there was no need for one because I feel like I’m just getting started, I’m at the very beginning trying to build proper discipline and expertise in things so I can make valuable contributions to the things/groups I care about. What is there to write about it when you’re just starting right?&lt;/p&gt;

&lt;p&gt;Later, after giving some more time to it, I started questioning myself if I’m heading in the right direction or not, which is when I thought to write about it because I think writing is the best way to reflect on things or life in general.&lt;/p&gt;

&lt;p&gt;Let’s dig in;&lt;/p&gt;

&lt;h3 id=&quot;health&quot;&gt;Health&lt;/h3&gt;
&lt;p&gt;Focusing on health was never prioritized on my list of things to do until I met Willie whom I bumped into while I was walking at the Ocean Beach (San Francisco) last year, 28th December evening (around 3 PM) to be precise. Willie is this 80-year-old man who comes for a quick walk every day at the beach and sometimes he brings along his sick/hospitalized friends (I don’t know anything about him beyond this). That day we ended up talking (mostly me listening) for more than 2 hours about our experiences in life. Of all the things we talked about what struck me the most was his thoughts on how not focusing on health made him and his friends (mostly his friends) miss doing simple/joy-full things in life.  At that moment I realized how little I care about my health and decided to make it part of my list immediately.&lt;/p&gt;

&lt;p&gt;At the start of this year, I thought I need to somehow hack this and invest some time on my health. I started out with cutting down sugar, calories, processed food. Tried running for a while (did 43 runs with an average of 3km), joined a cricket club (played about 5 matches), then I signed up for outdoor activities where I hiked MacRitchie Trail, climbed Mt Ophir and cycled 40kms of Singapore. By this time, I realized I had lost some fat and started focusing on building muscle. Then I signed up for a gym membership in September did it almost 4-5 times a week, never thought I could do this. Results? I lost up to 8kgs, have built good muscles, and feeling more fit in general. But there’s a lot more to do here and I’m always thinking about it.&lt;/p&gt;

&lt;h3 id=&quot;work&quot;&gt;Work&lt;/h3&gt;
&lt;p&gt;I improved a lot as an engineer over this year. This year at Grain, we shipped a whole new app (while supporting the old one) which is way snappier and has a lot of UI/UX improvements. We also built a dashboard (for incoming orders) which is regularly used by our chefs at kitchen hubs. This used to be on Google sheets, we moved it to React/GraphQL/Firebase which is super fast, real-time and maintainable.&lt;/p&gt;

&lt;p&gt;Some nerdy stuff; &lt;br /&gt;
The codebases (mostly mobile app) are more organized (with automated setup and health checks) now making it easier to contribute. We now have good assurances for the mobile app (tests with Jest and Detox, bit and pieces of Flow).&lt;/p&gt;

&lt;p&gt;We also made a lot of improvements to our development and deployment processes. We started using bots everywhere to manage deployments (using Fastlane, other scripts) and have health checks (using Danger) to maintain code quality and standards. We started deploying new features with feature flags and started selectively enabling them.&lt;/p&gt;

&lt;h3 id=&quot;travel&quot;&gt;Travel&lt;/h3&gt;
&lt;p&gt;Travel has always been my favorite/go-to activity to reflect, recharge and learn about myself. I don’t think I’ve traveled as much as I want to/could this year, but all those quick trips were really good and meaningful.&lt;/p&gt;

&lt;p&gt;I visited my parents twice this year, it felt good bonding with them and hanging out with friends back home. The best trip of this year was when I visited Italy for 2 weeks exploring the roots of my inspiration (Roman history and Renaissance). I roughly spent 2 weeks getting inspired and ticking off the bucket list in Rome, Florence, Venice, and Milan.&lt;/p&gt;

&lt;p&gt;Also finally, I started stepping out to visit South East Asian countries. I was in Malaysia (Johor) for a weekend to climb Mt. Ophir. I was in Indonesia (Batam, Bali) twice.&lt;/p&gt;

&lt;h3 id=&quot;reading&quot;&gt;Reading&lt;/h3&gt;
&lt;p&gt;One more year of good reading. I think I’m more happy with how I internalized some of the useful/good things I learned. I was picky and gave up on the uninteresting books/articles very quickly, I mean I was not scared/ashamed of giving up. I’m working on a system to translate the knowledge into actionable (some of them) so I can effectively apply it. Hoping this will help me to think and communicate clearly.&lt;/p&gt;

&lt;p&gt;That’s it, I’m still not sure if I’m on the right path, but I see myself becoming more disciplined and expert in what I’m doing and what I’m trying to become.&lt;/p&gt;

&lt;p&gt;👋🏻&lt;/p&gt;

&lt;figure&gt;
	&lt;img src=&quot;https://i.imgur.com/NEhwCGe.jpg&quot; /&gt;
	&lt;figcaption&gt;Sunset at the Ocean Beach, the one I shared with Willie&lt;/figcaption&gt;
&lt;/figure&gt;
</content>
 </entry>
 
 <entry>
   <title>React Native at Grain</title>
   
      <link href="https://twkrr.com/2019/04/21/react-native-at-grain/"/>
   
   <updated>2019-04-21T00:00:00-05:00</updated>
   <id>https://twkrr.com/2019/04/21/react-native-at-grain</id>
   <content type="html">&lt;p&gt;Last year, I joined Grain, an online food company, as a software engineer to work on mobile apps using React Native. During this one year, our code base grew by over a thousand commits. We shipped a lot of product features and I grew a love-hate relationship with React Native. Here are my thoughts and hopes about React Native and its future.&lt;/p&gt;

&lt;h3 id=&quot;tldr&quot;&gt;TLDR;&lt;/h3&gt;

&lt;p&gt;Many big companies don’t use React Native for variety of technical and organizational issues. But we at Grain love using it, for good reasons.&lt;/p&gt;

&lt;h3 id=&quot;grain-mobile-apps-stack&quot;&gt;Grain mobile apps stack&lt;/h3&gt;

&lt;p&gt;Using React Native, we developed and maintained two mobile apps — one for customers and one to facilitate backend operations. This is the tech stack for both apps.&lt;/p&gt;

&lt;figure&gt;
	&lt;img src=&quot;https://i.imgur.com/uc5CpGP.jpg&quot; /&gt;
	&lt;figcaption&gt;Grain Mobile apps stack&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;what-we-love-about-react-native&quot;&gt;What we love about React Native&lt;/h2&gt;

&lt;h3 id=&quot;javascript--react&quot;&gt;Javascript &amp;amp; React&lt;/h3&gt;

&lt;p&gt;I started off knowing nothing about iOS or Android apps. I tried learning. But the initial setup and the learning process took a long time and I soon lost interest. React Native eliminated the friction to get started and helped me develop mobile apps quickly without worrying much about platform and tools. Building apps with React made it easy for me to adopt React Native. Also, the strong community around Javascript and React kept me going.&lt;/p&gt;

&lt;p&gt;Before Grain, I built several products for early-stage startups with React and React Native. Over 2 years, I learned about iOS and Android platforms through my experience dealing with React Native. Later, I was able to write native modules and use them in production at Grain.&lt;/p&gt;

&lt;p&gt;It is easy for any developer to adapt to React or React Native. This encouraged me to onboard our web developers onto mobile codebase. Once onboarded, they started fixing things very quickly by sending PRs. As most of our developers are already familiar with Javascript, it also helped us understand and reuse business logic from other clients.&lt;/p&gt;

&lt;h3 id=&quot;great-developer-experience-with-code-sharing-hot-reloading&quot;&gt;Great Developer Experience (with code-sharing, hot reloading)&lt;/h3&gt;

&lt;p&gt;I enjoy working with React Native because it boosts my productivity. Unlike other hybrid app development frameworks, it also renders native components. This makes it super easy to write reusable code for both iOS and Android without compromising on basic performance. It’s easy even to separate the code based on the platform and maintain them within the same codebase using platform specific components.&lt;/p&gt;

&lt;p&gt;Mobile development is hard as it’s time-consuming. React Native solves this problem with hot reloading. Instant feedback on every small change on the app saves a lot of time and resources.&lt;/p&gt;

&lt;p&gt;Because it’s mostly Javascript and React, I had many other tools (react &amp;amp; redux devtools) to improve developer experience with better debugging and monitoring. It also helped me write quality code with speed.&lt;/p&gt;

&lt;h2 id=&quot;some-painful-memories&quot;&gt;Some painful memories&lt;/h2&gt;

&lt;h3 id=&quot;upgrading-react-native&quot;&gt;Upgrading React Native&lt;/h3&gt;

&lt;p&gt;We were still using React Native 0.27 until April 2018 because there was no active developer working on the Grain app. One of my first tasks at Grain was to upgrade the app to the latest version (which was 0.55 at that point). As there was no reliable way to do it, this upgrade was a painful experience. Also, there were many breaking changes, like metro blunder, to get to the latest version.&lt;/p&gt;

&lt;p&gt;We tried 2 strategies:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;To use &lt;a href=&quot;https://www.npmjs.com/package/react-native-git-upgrade&quot;&gt;react-native-git-upgrade&lt;/a&gt; and fix stuff&lt;/li&gt;
  &lt;li&gt;To manually change files using &lt;a href=&quot;https://github.com/ncuillery/rn-diff&quot;&gt;ncuillery/rn-diff&lt;/a&gt; and try upgrading&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nothing worked.&lt;/p&gt;

&lt;p&gt;I took the last resort and created a new app with the latest version, updated all the dependencies, recreated old deployment setup and ported over all of the React/Javascript code.&lt;/p&gt;

&lt;h3 id=&quot;linking-native-modules&quot;&gt;Linking native modules&lt;/h3&gt;

&lt;p&gt;Another common issue was linking native modules with the react-native link which used to be the rnpm link. It was unreliable. This was particularly hard on iOS because we always had missing search paths errors when linking a module. Sometimes the app would run well in debug mode but fail in release modes.&lt;/p&gt;

&lt;p&gt;Workarounds that worked for others often didn’t work for us.  We ended up linking our native modules manually and fixed Header/Framework search paths issues and maintained the fixes separately.&lt;/p&gt;

&lt;p&gt;This made it difficult for us to  decide what’s the right one to use or if we should build one on our own. That’s why I always thought  the React Native team should maintain some commonly used native modules like,&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Video&lt;/li&gt;
  &lt;li&gt;Internationalisation&lt;/li&gt;
  &lt;li&gt;Navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mobile OS’s and SDK’s get updated very regularly with new versions released every year and all of these new features only come with latest SDK’s (modules) which are not getting updated regularly (understand that open source contributors are busy). If React Native core team owns some of these modules and dedicate resources it will remove a lot of these pain points for extensive users.&lt;/p&gt;

&lt;h3 id=&quot;platform-specific-updates&quot;&gt;Platform specific updates&lt;/h3&gt;

&lt;p&gt;React Native has always kept us updated with new features from React, this helped us in shipping good experiences for our users by leveraging these new features (context API, lazy, memo, hooks etc…). This is precisely what we missed on the platform side, eg. supporting new Xcode build system, designing for the iPhone X (SafeAreaView). Sometimes I figured things out  by making mistakes, like upgrading to the latest macOS and then knowing that few things don’t work. We waited for the community to  fix/update these breaking changes and at times we wrote our own components/modules to handle these exceptions. Some of these updates came in slightly late but an active blog about when to upgrade and more from the core team would’ve definitely helped us to be more cautious. Again, not blaming anyone but these are some basic expectations for any mobile developer.&lt;/p&gt;

&lt;h3 id=&quot;performance&quot;&gt;Performance&lt;/h3&gt;

&lt;p&gt;We were quite happy with how our apps worked on iOS. They worked fine, w.r.t animations and were also using a limited amount of device resources. On the other hand, we had a few performance issues on Android which were caused by various reasons — some of which we fixed in a hackish way and some are just left out. Even down to Javascript, few React Native components worked fine on iOS but failed to render on Android and used to throw Layout errors.&lt;/p&gt;

&lt;p&gt;Few critical Android issues we faced were,&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Layout Errors and Type Errors like &lt;a href=&quot;https://github.com/facebook/react-native/issues/5507&quot;&gt;this&lt;/a&gt; and &lt;a href=&quot;https://github.com/facebook/react-native/issues/18773&quot;&gt;this&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Memory leak issues which made app junky&lt;/li&gt;
  &lt;li&gt;Flatlist with images performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same code used to work fine on iOS, but Android used to have regular issues like this which took additional time to debug and fix. Some of these issues are mistakes by developer (me) but the error messages gave no right directions to fix. We know the core team is aware of some of the other issues and are constantly working on to fix them.&lt;/p&gt;

&lt;p&gt;Finally, a few more things that could have improved our experience earlier on are clear documentations on developing with React Native, useful troubleshooting/debugging tools, and  optimistic updates. Lot of things get quickly deprecated in React world and it takes time for us to get out of dependency hell that gets created because of these deprications. Error messages are still cryptic, which we think can be more straightforward and useful. However, the huge red screens and yellow alerts helped us to some extent.&lt;/p&gt;

&lt;p&gt;Enough of the ranting, time to show some love.&lt;/p&gt;

&lt;h2 id=&quot;why-we-still-love-react-native&quot;&gt;Why we still love React Native&lt;/h2&gt;

&lt;p&gt;While dealing with our own issues and building products, we are always hopeful and looking forward to improvements in the framework. This always kept us curious with what’s happening in the community and we have been following the recent activities especially from the day Christoph started this little movement to make React Native great again.&lt;/p&gt;

&lt;p&gt;We really appreciate your &lt;a href=&quot;https://github.com/react-native-community/discussions-and-proposals/issues/64&quot;&gt;efforts&lt;/a&gt; to understand developer experiences and were super happy that you started &lt;a href=&quot;https://github.com/react-native-community/discussions-and-proposals/issues/104&quot;&gt;addressing&lt;/a&gt; most of them with project &lt;a href=&quot;https://github.com/facebook/react-native/issues/23313&quot;&gt;Lean Core&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, the &lt;a href=&quot;https://github.com/react-native-community&quot;&gt;community’s&lt;/a&gt; &lt;a href=&quot;https://github.com/facebook/react-native/issues/24032&quot;&gt;involvement&lt;/a&gt; is really inspiring. Big thanks to every one who’re spending loads of time perfecting this magic tool, you guys are awesome. All this work improves the developer experience and solves some of our (and many) problems which we deal with React Native on a daily basis. The work around new architecture (Fabric) and Turbo Modules is keeping us excited about the &lt;a href=&quot;http://blog.nparashuram.com/2019/01/react-natives-new-architecture-glossary.html&quot;&gt;future of React Native&lt;/a&gt;. We can’t wait to see all of this in action.&lt;/p&gt;

&lt;h2 id=&quot;whats-next-at-grain&quot;&gt;What’s next at Grain?&lt;/h2&gt;

&lt;p&gt;React Native helped many folks to build careers in mobile app development and also helped countless startups to build quality apps with less time and more productivity. We enjoyed using it and we can see how this framework is starting a revolution. This work, support and plans for React Native from core team and community will definitely improve in many areas, which we struggled with along the way. With this hope, we are confident in React Native and would continue to invest in it at Grain.&lt;/p&gt;

&lt;p&gt;In the coming weeks, we’re upgrading both of our apps to version 0.59+ and rewriting apps to support our new expansion plans.&lt;/p&gt;

&lt;p&gt;If this is something that excites you, please write to us at tech@grain.com.sg, we are looking for one senior front-end engineer to join us and build some cool stuff. We’re also hiring for mutiple positions, please take a look of other openings &lt;a href=&quot;https://grain.workable.com&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;👋🏻&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>2018: A year of uncertainties and possibilities</title>
   
      <link href="https://twkrr.com/2018/12/31/a-year-of-uncertainties-and-possibilities/"/>
   
   <updated>2018-12-31T00:00:00-06:00</updated>
   <id>https://twkrr.com/2018/12/31/a-year-of-uncertainties-and-possibilities</id>
   <content type="html">&lt;p&gt;I really don’t do these personal blogs but as I was away from my social circles all this year, I decided to write a small piece with all the updates and share what I have been up to all year long. I won’t lie, it did feel a little unnecessary in the beginning, but I thought it would also be a good way to reflect on my choices. I started writing it when I was in Caffe Trieste at San Francisco.&lt;/p&gt;

&lt;p&gt;It all looked very uncertain in the beginning and it still is, that is what remains even today but the only change I had during the journey is becoming comfortable with it and that comfort of enjoying and living in uncertainty is growing. Decisions like, quitting my first job at a startup which I’ve been working on since my college days, or deciding to go back to study, applying to colleges and getting rejected, or encouraging myself to lead mobile development at Grain, or deciding to do a solo trip to San Francisco were most uncertain options in the beginning and even now but what I’m learning and experiencing because all these decisions and journey is uncomfortably exciting.&lt;/p&gt;

&lt;p&gt;Started this year with very simple and small goals/milestones, and some wild ideas to unlearn habits and also disconnected from my social circles on Facebook and Instagram. Here’s me reflecting on all those choices I made and learnings I had this year.&lt;/p&gt;

&lt;h3 id=&quot;people&quot;&gt;People&lt;/h3&gt;

&lt;p&gt;I have become more comfortable with people this year. My social anxiety was crushed by kind love and hospitality by some amazing people, whom I meet at work and during travel. Starting from my colleagues at Grain, clients in Dubai, co-travellers in Singapore and San Francisco inspired and taught me a lot of good qualities to treat people better and make them happy in every way possible.&lt;/p&gt;

&lt;p&gt;Hangouts with colleagues at work, best conversations with friends and co-travellers, Christmas Eve celebrations with bunch of amazing travellers glorified my happiness this year.&lt;/p&gt;

&lt;h3 id=&quot;work&quot;&gt;Work&lt;/h3&gt;

&lt;p&gt;I have done most satisfying work this year. I’m actively engaged in developing and maintaining 2 software products for Grain. Finally I’m owning products that are serving the purpose of a company which is trying to do some good. We also have some exciting stuff coming up in 2019, can’t wait for it.&lt;/p&gt;

&lt;p&gt;I also helped my friend to launch their product, this gave me some adrenaline rush. We have built some amazing hardware and software products in short time and deployed at a very large event in Dubai.&lt;/p&gt;

&lt;h3 id=&quot;travel&quot;&gt;Travel&lt;/h3&gt;

&lt;p&gt;Deciding to travel a bit early this year had a huge impact on me. The experiences I had with diverse culture, people, history and food were incredible. I travelled for almost 7 weeks and was in 4 countries this year, longest until now.&lt;/p&gt;

&lt;p&gt;Stayed in Dubai for almost 2 weeks to deploy an event management tech solution at Madinat Jumeirah. Later, I explored the futuristic constructions, artistic palaces, and tasty middle eastern food. Visited 148th floor of Burj Khalifa, did desert safari, and some other touristy stuff. The best thing? I got my Macbook screen replaced for free in Apple Store at Mall of Emirates.&lt;/p&gt;

&lt;p&gt;Visited first and later settled in Singapore. I had amazing experiences with the people of Singapore, her culture, and food. I’m working here with some incredible (kind and intelligent) people who are teaching me a lot about exploring and experiencing the world in many different ways. Also, I visited some museums, libraries, hawker centres, and not to forget, some fantastic bars.&lt;/p&gt;

&lt;p&gt;Stayed in San Francisco Bay Area &amp;amp; Silicon Valley for 2 weeks exploring The Beats, city’s history, art scene, tech scene, and food. It always felt like I visited this place thousand times even before I was here, I need days to explain the experiences I had in this city. Had many fanboy moments while visiting all my favourite places. I started as a tourist but ended up being a traveller: I learned a lot about travelling on this trip. Met very interesting people from Norway, Russia, Brazil, Japan, China, and Saudi Arabia.&lt;/p&gt;

&lt;h3 id=&quot;reading&quot;&gt;Reading&lt;/h3&gt;

&lt;p&gt;2018 was an incredible year for reading. I made enough time to read 20+ books and loads of other pieces of information on interesting things. Spent good amount of time in libraries around Singapore. I also started maintaining office library at Grain (I should get better at this).&lt;/p&gt;

&lt;h3 id=&quot;the-year-of-many-firsts&quot;&gt;The year of many firsts&lt;/h3&gt;

&lt;p&gt;— First professional software engineering job &lt;br /&gt;
— First stay out of home &lt;br /&gt;
— First visit to Dubai &lt;br /&gt;
— First visit to Singapore &lt;br /&gt;
— First visit to San Francisco and first solo trip &lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;other-first-and-fun-things&quot;&gt;Other first and fun things&lt;/h3&gt;

&lt;p&gt;— First Tesla ride &lt;br /&gt;
— First business class flight &lt;br /&gt;
— Chef’s and friends at Grain made me taste varieties of food for first time &lt;br /&gt;
— First broadway show &lt;br /&gt;
— Tons of live music, Netflix, and alcohol tasting &lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;what-i-could-have-done-better-in-2018-no-regrets&quot;&gt;What I could have done better in 2018 (No REGRETS!)&lt;/h3&gt;

&lt;p&gt;— With a lot of food thing happening in my life, I’ve consumed tons of calories. I didn’t spend good amount of time burning those calories. &lt;br /&gt;
— I still suck at single-tasking and deep work. &lt;br /&gt;
— I consumed a lot of information and didn’t apply some of that. I needed to find that balance between consumption and application with proper diet. &lt;br /&gt;
— Made some less valuable financial investments and acquired some unhealthy spending habits. Not a big loss but I’m a bit concerned about the bad habits. &lt;br /&gt;
— I missed a chance to travel to China because of incorrect work estimations. But the work was satisfying. &lt;br /&gt;&lt;/p&gt;

&lt;p&gt;It’s been a very productive and memorable year, it all started with uncertainties and ending up with possibilities. Being honest to self, comfortable with uncertainty, being unattached, and giving less attention to less valuable things had helped me in having a great journey this year. Also, I’m very thankful for everyone who made it possible, especially to my amazing friends at Grain. I’m excitedly looking forward to all the good things I’m going to do in the new year.&lt;/p&gt;

&lt;p&gt;👋🏻&lt;/p&gt;
</content>
 </entry>
 

</feed>
