[{"data":1,"prerenderedAt":315},["ShallowReactive",2],{"search-navigation":3,"footer-profile":26,"projects-page":59,"search-projects":267},[4],{"title":5,"path":6,"stem":7,"children":8,"page":25},"Blog","\u002Fblog","blog",[9,13,17,21],{"title":10,"path":11,"stem":12},"AWS AppRunner","\u002Fblog\u002Faws-apprunner","blog\u002Faws-apprunner",{"title":14,"path":15,"stem":16},"Pre-commit hook setup with husky","\u002Fblog\u002Fprecommit-hook-setup","blog\u002Fprecommit-hook-setup",{"title":18,"path":19,"stem":20},"AWS S3 storage tiers","\u002Fblog\u002Fs3-storage-tiers","blog\u002Fs3-storage-tiers",{"title":22,"path":23,"stem":24},"Serverless Cloudformation Parameters","\u002Fblog\u002Fserverless-cfn-params","blog\u002Fserverless-cfn-params",false,{"id":27,"email":28,"extension":29,"headline":30,"heroSummary":31,"meta":32,"name":33,"resumeSummary":34,"role":35,"site":36,"socials":37,"stem":50,"techLine":51,"__hash__":58},"profile\u002Fdata\u002Fprofile.yml","me@rajan.work","yml","I build reliable cloud and AI systems.","Senior software engineer building production systems on AWS—distributed backends, event-driven architectures, containerized workloads, and GenAI applications—engineered for reliability, security, observability, and cost.",{},"Rajan Kalwar","Senior software engineer focused on AWS architecture, distributed backends, and production GenAI. I design secure APIs, event-driven workflows, container platforms, data models, and LLM applications—with explicit attention to deployment, permissions, failure behavior, and operational trade-offs.","Senior Software Engineer","rajan.work",[38,42,46],{"label":39,"icon":40,"to":41},"Rajan Kalwar on GitHub","i-simple-icons-github","https:\u002F\u002Fgithub.com\u002Frajandmr",{"label":43,"icon":44,"to":45},"Rajan Kalwar on X","i-simple-icons-x","https:\u002F\u002Ftwitter.com\u002Frajandmr",{"label":47,"icon":48,"to":49},"Email Rajan Kalwar","i-lucide-mail","mailto:me@rajan.work","data\u002Fprofile",[52,53,54,55,56,57],"AWS","Python","TypeScript","Serverless","Containers","GenAI","bzXg8fbb4-V3aF5qTVsw-_kvxT7uc_pHnevoZYvDCKI",{"id":60,"additional":61,"extension":29,"featured":145,"meta":264,"stem":265,"__hash__":266},"projects\u002Fdata\u002Fprojects.yml",[62,85,107,124],{"id":63,"title":64,"flow":65,"summary":66,"highlights":67,"stack":72,"repo":81,"resumeBlurb":84},"streaming-llm-responses-from-lambda","Streaming LLM responses from Lambda","Client → Lambda Function URL → Web Adapter → Flask → OpenAI-compatible LLM API","A single Lambda function streams chat-completion responses back to the client token-by-token as Server-Sent Events, using a Lambda Function URL in response-streaming mode and the AWS Lambda Web Adapter to bridge a Flask app onto the stock managed Python runtime.",[68,69,70,71],"Achieves true response streaming without a custom runtime or container by stacking the Web Adapter with a `RESPONSE_STREAM` Function URL","Forwards only each completion delta as an SSE data frame, ends with the `[DONE]` sentinel, and pushes errors onto a named event channel rather than the data stream","Ships a dependency-free browser tester built on the Fetch ReadableStream API with an `AbortController` stop button — the endpoint is POST, so `EventSource` is not an option","Documents secret handling through `.env` and `useDotenv`, and explicitly warns that the demo endpoint is unauthenticated, so anyone with the URL can invoke it and consume the upstream key",[73,74,75,76,77,78,79,80],"Python 3.12","Flask","Lambda Function URLs","Lambda Web Adapter","SSE","AWS Lambda Powertools","OpenAI SDK","Serverless Framework",{"label":82,"url":83},"View Lambda streaming repository","https:\u002F\u002Fgithub.com\u002Frajandmr\u002Faws-lambda-streaming","Token-by-token delivery with Lambda Web Adapter, Flask, and Server-Sent Events.",{"id":86,"title":87,"flow":88,"summary":89,"highlights":90,"stack":95,"repo":103,"resumeBlurb":106},"appsync-graphql-authorization-patterns","AppSync GraphQL authorization patterns","Client → AppSync GraphQL → Lambda resolvers → DynamoDB","Provisioned two managed AppSync GraphQL APIs in one stack, each backed by direct Lambda resolvers performing DynamoDB CRUD, to contrast distinct authentication and authorization strategies.",[91,92,93,94],"The Todos API exposes full CRUD behind API-key authentication, with IAM as a secondary provider","The Orders API uses Cognito User Pools as the primary provider and an API key for reads, while `createOrder` is gated to authenticated Cognito users through `@aws_cognito_user_pools` directives plus an in-code identity guard","Stamps the caller's Cognito `sub` as the order's `customerId`, so record ownership cannot be spoofed by the client","Enables AppSync request logging at the `ALL` level on both APIs alongside structured Lambda logs",[96,97,98,99,100,73,101,78,102,80],"AppSync","Cognito","Lambda","DynamoDB","IAM","GraphQL","Pydantic",{"label":104,"url":105},"View AppSync GraphQL repository","https:\u002F\u002Fgithub.com\u002Frajandmr\u002Fappsync-gql","API-key, IAM, Cognito, and field-level authorization examples.",{"id":108,"title":109,"flow":110,"summary":111,"highlights":112,"stack":117,"repo":120,"resumeBlurb":123},"eventbridge-routing-and-decoupled-consumers","EventBridge routing and decoupled consumers","Client → API Gateway HTTP API → Lambda → EventBridge bus → consumer Lambdas","Built an HTTP-to-EventBridge system where one producer publishes domain events to a custom bus and multiple consumers subscribe through content-based rules.",[113,114,115,116],"Demonstrates fan-out and content-based routing — an `orders` event fans out to two consumers, while a `notifications` event matches a two-field `source` + `detail-type` rule","Shows the same rule authored two ways: as Serverless `eventBridge` triggers and as raw CloudFormation rules with `SourceArn`-scoped invoke permissions","Publishes through a Pydantic envelope that supports both a flat default and a caller-controlled `source` \u002F `detail-type` \u002F `detail` payload","Keeps IAM tight — the producer can `PutEvents` only to the one custom bus — and documents at-least-once delivery plus the idempotency, retry, dead-letter, and alarm work needed before production use",[118,119,98,100,73,78,102,80],"EventBridge","API Gateway HTTP API",{"label":121,"url":122},"View EventBridge repository","https:\u002F\u002Fgithub.com\u002Frajandmr\u002FEventbridge-Lambda-Orchestration","Domain-event routing with independently subscribed consumers.",{"id":125,"title":126,"flow":127,"summary":128,"highlights":129,"stack":134,"repo":141,"resumeBlurb":144},"multi-az-vpc-and-private-dns","Multi-AZ VPC and private DNS","Internet → IGW → public subnets · NAT → private subnets · Route 53 private DNS","Provisioned a two-Availability-Zone VPC with public and private subnets, a cost-optimized single NAT gateway, a bastion host, two private EC2 hosts, and a Route 53 private hosted zone so every host resolves by name from inside the network.",[130,131,132,133],"Keeps the stack region-portable — Availability Zones via `GetAZs` and Amazon Linux 2023 AMIs via the AWS SSM public parameter, with no hardcoded IDs","Layers access so private hosts accept SSH only from the bastion's security group by reference rather than CIDR, and generates the EC2 key pair as an AWS resource that stores encrypted private material in SSM Parameter Store","Defaults to encrypted `gp3` EBS on every host and splits the stack into one CloudFormation concern per file for readability","Exposes plain stack outputs (VPC, bastion IP, key material path, private DNS names) and flags the open bastion SSH rule as demo-only to lock down before real use",[135,136,137,138,139,140],"VPC","EC2","Route 53","NAT Gateway","SSM Parameter Store","CloudFormation (via Serverless Framework)",{"label":142,"url":143},"View networking stack repository","https:\u002F\u002Fgithub.com\u002Frajandmr\u002Faws-networking-stack","Public\u002Fprivate subnet architecture with NAT, bastion access, and Route 53 private DNS.",[146,183,219],{"id":147,"title":148,"flow":149,"context":150,"ownership":151,"decisions":152,"outcome":158,"stack":159,"repos":163,"home":167,"resume":175},"api-access-management-and-usage-controls","API access management and usage controls","Client → API Gateway REST API → Lambda → DynamoDB","Teams needed a deployable, AWS-native pattern for issuing API keys and binding them to tier-specific throttles and quotas — without standing up a custom rate-limiting service.","I designed and implemented the management API, the DynamoDB data model, the IAM boundaries, the usage-plan reconciliation, and the operational documentation.",[153,154,155,156,157],"Kept the raw API-key value out of DynamoDB entirely — it is returned to the caller exactly once at creation, and only the API Gateway key id and lifecycle metadata are persisted","Modeled keys and plans in a single DynamoDB table with an entity-type GSI (`KEY` and `PLAN` entities), keeping access patterns simple and the table on-demand priced","Made API Gateway the enforcement point: key validity, throttles, and quotas are checked before the protected workload Lambda is ever invoked, so there is no rate-limiting in application code","Scoped the manager's IAM to specific DynamoDB and API Gateway resource ARNs (api keys, usage plans, REST APIs) rather than wildcards, and left the protected workload Lambda with logs-only permissions","Treated DynamoDB as the source of truth with usage plans created at runtime by the manager rather than declared in the stack — a deliberate trade-off that keeps the table authoritative at the cost of orphaning runtime keys and plans on stack teardown","A focused, security-conscious reference for the full API-key and usage-plan lifecycle — creation, tier binding, runtime updates, and disabling — built on managed AWS controls with least-privilege permissions.",[73,160,98,99,100,161,162,80],"API Gateway REST API","AWS Lambda Powertools v3","Pydantic v2",[164],{"label":165,"url":166},"View API management repository","https:\u002F\u002Fgithub.com\u002Frajandmr\u002Fapi-management",{"title":168,"flow":169,"summary":170,"highlights":171,"repo":174},"API access controls with native AWS services","Client → API Gateway → Lambda → DynamoDB","Designed a deployable access-control system using API Gateway usage plans for tier-specific throttles and quotas. A Lambda management API handles key and plan lifecycles, while DynamoDB stores metadata without retaining raw credentials.",[172,173],"Isolated administrative operations from protected workloads","Made propagation delays and non-transactional boundaries explicit","View repository",{"summary":176,"decisions":177,"outcome":181,"stack":182},"Designed and implemented an AWS-native control plane for issuing API keys and applying tier-specific throttles and quotas without building a custom rate limiter.",[178,179,180],"Separated administrative key and plan operations from API-key-protected workloads.","Returned raw key values only at creation; DynamoDB stores lifecycle metadata using a single-table model and entity-type index.","Documented propagation delays, non-transactional edge cases, and cleanup behavior as explicit operating constraints.","A deployable reference for the complete API-key and usage-plan lifecycle using managed AWS controls and least-privilege permissions.","Python 3.12 · API Gateway REST API · Lambda · DynamoDB · IAM · AWS Lambda Powertools · Serverless Framework",{"id":184,"title":185,"flow":186,"context":187,"ownership":188,"decisions":189,"outcome":195,"stack":196,"repos":199,"home":203,"resume":211},"failure-aware-asynchronous-fan-out","Failure-aware asynchronous fan-out","HTTP API → Lambda → SQS → Lambda → SNS → Consumers","An incoming HTTP request needed to become independently consumable notification and audit events without coupling those consumers to the request path or making the client wait for them.","I built the producer, the queue processor, the fan-out topics, the consumer functions, the IAM, and the failure behavior as a single deployable system.",[190,191,192,193,194],"Acknowledged the request with HTTP 202 the moment it was safely queued, decoupling client latency from downstream processing","Set the queue visibility timeout well above the processor timeout and moved messages to a dead-letter queue after three failed receives, retaining the DLQ for the full SQS maximum so poisoned messages are never silently dropped","Used partial batch failure reporting so a single bad record retries itself rather than re-driving the whole batch","Scoped every grant to the exact resource it needs (`sqs:SendMessage` to the processing queue, `sns:Publish` to the two topics) rather than granting broad queue or topic access","Documented propagation, retry, and non-atomic edge cases explicitly so the buffering, dead-letter, and fan-out behavior is read as deliberate operating constraints","A reference pipeline with explicit buffering, fan-out, retry, and dead-letter isolation, where every IAM grant is resource-scoped and the failure path is observable rather than silent.",[73,119,98,197,198,100,80],"SQS","SNS",[200],{"label":201,"url":202},"View SNS\u002FSQS fan-out repository","https:\u002F\u002Fgithub.com\u002Frajandmr\u002Fsns-sqs-fanout",{"title":204,"flow":205,"summary":206,"highlights":207,"repo":174},"Resilient asynchronous fan-out","HTTP API → Lambda → SQS → SNS → Consumers","Engineered an event pipeline that buffers HTTP requests in SQS, processes them asynchronously with Lambda, and distributes results to independent notification and audit consumers through SNS.",[208,209,210],"Decoupled request handling through durable queueing","Retried only failed batch items and routed exhausted messages to a dead-letter queue","Scoped producers and processors to their minimum required permissions",{"summary":212,"decisions":213,"outcome":217,"stack":218},"Built a deployable event pipeline that buffers HTTP requests, processes them asynchronously, and fans out notification and audit events to independently operated consumers.",[214,215,216],"Kept the queue visibility timeout above the processor timeout and isolated exhausted messages in a dead-letter queue after three failed receives.","Used partial batch failure reporting so successful records are not processed again when another record fails.","Scoped every IAM grant to the exact queue or topic it needs, rather than granting broad messaging access.","A failure-aware reference pipeline with explicit buffering, retry, dead-letter isolation, and consumer decoupling.","Python 3.12 · API Gateway HTTP API · Lambda · SQS · SNS · IAM · Serverless Framework",{"id":220,"title":221,"flow":222,"context":223,"ownership":224,"decisions":225,"outcome":231,"stack":232,"repos":241,"home":248,"resume":256},"private-container-services-on-aws","Private container services on AWS","Internet → ALB → Private subnets → ECS service","Engineering teams often need to compare Fargate-managed capacity with EC2-backed ECS while preserving the same secure network, delivery, and image-handling model.","I created two parallel implementations — Fargate and EC2 — covering networking, IAM, security groups, load balancing, ECR, capacity, and the ECS services.",[226,227,228,229,230],"Kept tasks and container instances in private subnets with no public IP, reachable only through an internet-facing ALB whose security group is the sole permitted source to the service","Used `awsvpc` networking with IP-target registration so the ALB talks directly to task ENIs, and added the listener dependency that prevents the classic ALB\u002FECS creation race","Solved the image-before-service chicken-and-egg with a single stack and a CloudFormation condition: the first deploy stands up the VPC, ALB, ECR, and task definition; the second — after the image is pushed — creates the service","Kept the application's task role intentionally empty (the API calls no AWS services) and separated it from the execution role that only pulls the image and writes logs","Provisioned the EC2 variant with an Auto Scaling group governed by an ECS capacity provider with managed scaling, IMDSv2 required, and SSM-resolved AMIs — a direct comparison against Fargate-managed capacity on identical networking and delivery foundations","Two directly comparable, deployable architectures that make the capacity-model trade-off — managed Fargate versus self-managed EC2 with a capacity provider — concrete and operational.",[233,234,235,236,237,238,135,239,240,80],"ECS","Fargate","EC2 Auto Scaling","ECS capacity provider","ECR","ALB","Docker","Python 3.12 \u002F Flask",[242,245],{"label":243,"url":244},"View Fargate repository","https:\u002F\u002Fgithub.com\u002Frajandmr\u002Fecs-fargate-service",{"label":246,"url":247},"View ECS on EC2 repository","https:\u002F\u002Fgithub.com\u002Frajandmr\u002Fecs-ec2-private-service",{"title":249,"flow":250,"summary":251,"highlights":252,"repo":243},"Private ECS services with explicit capacity trade-offs","Internet → ALB → Private subnets → ECS","Built comparable Fargate and EC2-backed ECS services behind an Application Load Balancer, keeping application workloads in private subnets while making the capacity-ownership trade-offs directly comparable.",[253,254,255],"Kept tasks and container instances off the public internet","Separated networking, capacity, image, and service concerns","Sequenced infrastructure and image delivery before service rollout",{"summary":257,"decisions":258,"outcome":262,"stack":263},"Created parallel Fargate and EC2-backed ECS implementations to compare capacity models while preserving the same private networking, load-balancing, and image-delivery boundaries.",[259,260,261],"Kept tasks and container instances in private subnets behind a public Application Load Balancer.","Split networking, capacity, image, and service resources by operational concern and staged deployment so ECR existed before service rollout.","Configured the EC2 implementation with an Auto Scaling group and ECS capacity provider for a direct comparison with Fargate-managed capacity.","Two deployable architectures that make the infrastructure ownership and capacity-management trade-off concrete.","ECS · Fargate · EC2 Auto Scaling · ECS capacity provider · ECR · ALB · VPC · Docker · Serverless Framework",{},"data\u002Fprojects","SMOxTvm3Djp6YrRMMeBOkFECxpFNrBXgGHfihKfM7Ks",{"id":60,"additional":268,"extension":29,"featured":285,"meta":314,"stem":265,"__hash__":266},[269,273,277,281],{"id":63,"title":64,"flow":65,"summary":66,"highlights":270,"stack":271,"repo":272,"resumeBlurb":84},[68,69,70,71],[73,74,75,76,77,78,79,80],{"label":82,"url":83},{"id":86,"title":87,"flow":88,"summary":89,"highlights":274,"stack":275,"repo":276,"resumeBlurb":106},[91,92,93,94],[96,97,98,99,100,73,101,78,102,80],{"label":104,"url":105},{"id":108,"title":109,"flow":110,"summary":111,"highlights":278,"stack":279,"repo":280,"resumeBlurb":123},[113,114,115,116],[118,119,98,100,73,78,102,80],{"label":121,"url":122},{"id":125,"title":126,"flow":127,"summary":128,"highlights":282,"stack":283,"repo":284,"resumeBlurb":144},[130,131,132,133],[135,136,137,138,139,140],{"label":142,"url":143},[286,295,304],{"id":147,"title":148,"flow":149,"context":150,"ownership":151,"decisions":287,"outcome":158,"stack":288,"repos":289,"home":291,"resume":293},[153,154,155,156,157],[73,160,98,99,100,161,162,80],[290],{"label":165,"url":166},{"title":168,"flow":169,"summary":170,"highlights":292,"repo":174},[172,173],{"summary":176,"decisions":294,"outcome":181,"stack":182},[178,179,180],{"id":184,"title":185,"flow":186,"context":187,"ownership":188,"decisions":296,"outcome":195,"stack":297,"repos":298,"home":300,"resume":302},[190,191,192,193,194],[73,119,98,197,198,100,80],[299],{"label":201,"url":202},{"title":204,"flow":205,"summary":206,"highlights":301,"repo":174},[208,209,210],{"summary":212,"decisions":303,"outcome":217,"stack":218},[214,215,216],{"id":220,"title":221,"flow":222,"context":223,"ownership":224,"decisions":305,"outcome":231,"stack":306,"repos":307,"home":310,"resume":312},[226,227,228,229,230],[233,234,235,236,237,238,135,239,240,80],[308,309],{"label":243,"url":244},{"label":246,"url":247},{"title":249,"flow":250,"summary":251,"highlights":311,"repo":243},[253,254,255],{"summary":257,"decisions":313,"outcome":262,"stack":263},[259,260,261],{},1789539344950]