Categorias
PHP Programação

A bref AWS PHP story – Part 2

We are starting Part 2 of the Series "A bref AWS PHP history". You can check Part 1, where I presented the PHP language as a reliable and good alternative for Serverless applications.

Part 2 is to show how CDK will describe more AWS resource dependencies; how policies and roles are involved in this process; how to test if they are applied as expected; and how PHP services will use those resources.

Some of those topics seem straightforward to some people, but I would like to avoid guessing that this is known to the audience since I have experienced some PHP developers struggling to put all these together for the first time due to the paradigm change. It should be fun.

Table of contents:

  1. What else are we doing?
  2. Describing more AWS services - Adding an S3 bucket
  3. Services permissions
  4. Testing CDK
  5. PHP and AWS Services
    1. Handlers
    2. Application, Domain, Infrastructure, etc
  6. Wrap-up
  7. P.S.: Stats

What else are we doing?

The Part 1 function was returning a Fibonacci result from an int. Very simple. We will keep it simple for now to focus on putting the PHP code into a lambda and allowing PHP code to interact with AWS Services.

The computing complexity is irrelevant because it could be very complex logic or very simple, and the topics we are discussing in this part of the series will use the same design.

The lambda will now use the result of the Fibonacci of a provided integer or a random integer from 400 to 1000 (to get a good image and not to overflow integer). This integer is the number of pixels of an image from the bucket and an arbitrary request metadata we are creating. If the image does not exist, the lambda will fetch a random image from the web with that number of pixels, save it and generate the metadata.

Get the part-2 source-code on GitHub and the diff from part-1.

Describing more AWS services - Adding an S3 bucket

S3 buckets are simple yet compelling services for multipurpose workloads. It will be added to the series as a basic storage mechanism. The lambda function, now called GetFibonacciImage function, will need some permissions to manage the bucket.

Starting from the bucket definition, CDK give fantastic constructs, and it goes like this:

cdk-stack.ts

    const brefBucket = new Bucket(this, `${stackPrefix}Bucket`, {
      autoDeleteObjects: true,
      removalPolicy: RemovalPolicy.DESTROY,
    });

By default, buckets will not be deleted during a CDK destroy because they need to be empty. So you will have a hanging bucket in your account. I don't want to keep those contents if the lambda no longer exists. Then autoDeleteObjects and removalPolicy options are selected to enable the destruction of the buckets and their contents if I execute a stack destroy.

We want to decouple the configuration from the implementation to have a more SOLID code. That way, we avoid hard-coded configuration, making our code cleaner and more robust. Then, the code is ready to work, no matter the bucket name.

The implementation code is aware that the name will come from an environment variable and will work with that (yes, if you think that test will be easy to write, you are right):

cdk-stack.ts

and

      environment: {
        BUCKET_NAME: brefBucket.bucketName,
      }

Services permissions

There is a Lambda Function and an S3 Bucket. The described use case determines that the lambda needs read and write permissions to the bucket. And nothing more. It is a good practice to give the minimum necessary permission to a resource:

cdk-stack.ts

    brefBucket.grantReadWrite(getLambda);

The result is a list of actions added to the policy recommended by AWS for operations requiring only read and write.

          Action: [
            "s3:GetObject*",
            "s3:GetBucket*",
            "s3:List*",
            "s3:DeleteObject*",
            "s3:PutObject",
            "s3:PutObjectLegalHold",
            "s3:PutObjectRetention",
            "s3:PutObjectTagging",
            "s3:PutObjectVersionTagging",
            "s3:Abort*",
          ],

Testing CDK

Testing is a great feature of CDK, and we can see how tests can verify our changes with npm t:

That there is a function

  const functionName = 'GetFibonacciImage';
  /* ... */
  it('Should have a lambda function to get fibonacci', () => {
    template.hasResourceProperties('AWS::Lambda::Function', {
      Layers: [Cdk.CdkStack.brefLayerFunctionArn],
      FunctionName: functionName,
    });
  });

And if only the permissions the lambda needs were granted:

  it('Should have a policy for S3', () => {
    template.hasResourceProperties('AWS::IAM::Policy', {
      PolicyName: Match.stringLikeRegexp(`^${stackPrefix}${functionName}ServiceRoleDefaultPolicy`),
      PolicyDocument: {
        Statement: [{
          Action: [
            "s3:GetObject*",
            "s3:GetBucket*",
            "s3:List*",
            "s3:DeleteObject*",
            "s3:PutObject",
            "s3:PutObjectLegalHold",
            "s3:PutObjectRetention",
            "s3:PutObjectTagging",
            "s3:PutObjectVersionTagging",
            "s3:Abort*",
          ],
        }],
      },
    });
  });

You may want to check cdk-stack.test.ts to see more details.

PHP and AWS Services

This is the part where we have fewer serverless needs impacting the code, as the PHP code will follow the same logic we might be using to communicate with AWS services on any other platform overall (there are always some specific use cases).

The reuse of the same existing logic is excellent. It leverages the decision to keep using PHP when moving that workload to Serverless, as the bulk of the knowledge and already proven code would remain as-is. We may escape the trap of classifying that PHP code as legacy as if it should be avoided, terminated or hated.

As a side note, a few external layers of our software architecture are touched if a good software architecture was applied before. Therefore, during the implementation of this architectural change, it should be quick to realise how beneficial and time-saving it is to have a well-architectured application with a balanced decision for patterns, principles, and designs to be applied, ultimately giving flexibility to the application and its features.

The handler is simplified now and should accommodate everything to a class in the direction of following SRP, a principle that we are bringing to the code during the code bites:

Handlers

php/handler/get.php

return function ($request, $context) {
    return \BrefStory\Application\ServiceFactory::createGetFibonacciImageHandler()
        ->handle($request, $context)
        ->toApiGatewayFormatV2();
};

To handle the request details, the Fibonacci code now lives in a proper event handler (implements Bref\Event\Handler).

php/src/Event/Handler/GetFibonacciImageHandler.php

    public function handle($event, Context $context): HttpResponse
    {
        $int = (int) (
            $event['queryStringParameters']['int'] ?? random_int(
                self::MIN_PIXELS_FOR_REASONABLE_IMAGE_AND_NOT_BIG_FIBONACCI,
                self::MAX_PIXELS_FOR_REASONABLE_IMAGE_AND_NOT_BIG_FIBONACCI
            )
        );

        $metadata = $this->photoService->getJpegImageFor($int);

        $responseBody = [
            'context' => $context,
            'now' => $this->dateTimeImmutable()->format('Y-m-d H:i:s'),
            'int' => $int,
            'fibonacci' => $this->fibonacci($int),
            'metadata' => $metadata,
        ];

        $response = new JsonResponse($responseBody);

        return new HttpResponse($response->getContent(), $response->headers->all());
    }

We would also like to start testing the PHP code. As the Event Handler might be a new layer (although very similar to widely used controllers), php/tests/unit/Event/Handler/GetFibonacciImageHandlerTest.php test class was created for that. The part-2 will only focus on this test class to avoid overloading with too many changes, but we would usually have test coverage for all the code in the repository.

Applications, domains, infrastructure, etc

Finally, we are inside the layers where we are most used to. To fit our purposes, the Event Handler will depend on and call an Application layer service that will orchestrate all the steps to fetch the image metadata.

php/src/Application/PicsumPhotoService.php#L34-L42

    public function getJpegImageFor(int $imagePixels): array
    {
        try {
            return $this->getImageFromBucket($imagePixels);
        } catch (NoSuchKeyException) {
            // do nothing
        }

        return $this->fetchAndSaveImageToBucket($imagePixels);
    }

The interesting thing to mention about using AWS Services is how simple S3Client is instantiated. There is a factory to create service:

php/src/Application/ServiceFactory.php#L22-L29

    public static function createPicsumPhotoService(): PicsumPhotoService
    {
        return new PicsumPhotoService(
            HttpClient::create(),
            new S3Client(),
            getenv('BUCKET_NAME'),
        );
    }
  • new S3Client is all we need because the environment will use AWS credentials, provided to lambda at execution time, as an assumed role that will carry the policies we defined in the CDK constructs stack, i.e., with read and write permissions to the bucket
  • getenv('BUCKET_NAME'), which is gracefully provided by CDK when creating our bucket with any dynamic name it pleases to

I asked ChatGPT about this class:

The PicsumPhotoService class seems to be following the Single Responsibility Principle (SRP) as it has only one responsibility, which is to provide methods for fetching and saving JPEG images from the Picsum website.

The class has methods to fetch the image from an S3 bucket, and if it's not available, fetches it from the Picsum website, saves it to the S3 bucket, and creates and puts metadata for the image in the S3 bucket.

The class has a clear separation of concerns, where the S3Client and HttpClientInterface are injected through the constructor, and the different functionalities are implemented in separate private methods. Additionally, each method is doing a single task, which makes the code easy to read, test, and maintain.

Therefore, it can be concluded that the PicsumPhotoService class follows SRP.

Wrap-up

It would be simple like that. Check more details in the source code, install it and try it yourself. This project is ready to:

  • Create a lambda function using Bref
  • Create an S3 Bucket with read and write permissions to the lambda
  • Test the stack Cloudformation code
  • Separate the PHP logic
  • Have PHP communicating with AWS Services
  • Start PHP testing

P.S.: Stats

I did not plan to talk widely about stats now, but I think I can share the most two significant measures I had with this simple code so far.

[Update 22/03/23] Using https://k6.io/

1 - With a brand new stack and a cold lambda:

scenarios: (100.00%) 1 scenario, 200 max VUs, 2m30s max duration (incl. graceful stop):
           * default: 200 looping VUs for 2m0s (gracefulStop: 30s)

     data_received..................: 49 MB  409 kB/s
     data_sent......................: 7.8 MB 65 kB/s
     http_req_blocked...............: avg=2.36ms   min=671ns    med=2.27µs   max=581.87ms p(90)=4.18µs   p(95)=7µs
     http_req_connecting............: avg=712.63µs min=0s       med=0s       max=193.34ms p(90)=0s       p(95)=0s
     http_req_duration..............: avg=531.51ms min=204.46ms med=485.24ms max=3.81s    p(90)=517.98ms p(95)=534.3ms
       { expected_response:true }...: avg=513.6ms  min=204.46ms med=485.07ms max=3.67s    p(90)=516.62ms p(95)=531.5ms
     http_req_failed................: 0.60%  ✓ 272        ✗ 44761
     http_req_receiving.............: avg=123.76µs min=13.77µs  med=44.04µs  max=16.78ms  p(90)=71.27µs  p(95)=85.71µs
     http_req_sending...............: avg=14.79µs  min=4.27µs   med=12.43µs  max=402.74µs p(90)=23.97µs  p(95)=31.4µs
     http_req_tls_handshaking.......: avg=1.37ms   min=0s       med=0s       max=330.58ms p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=531.37ms min=204.36ms med=485.11ms max=3.81s    p(90)=517.77ms p(95)=534.13ms
     http_reqs......................: 45033  373.683517/s
     iteration_duration.............: avg=533.96ms min=204.55ms med=485.34ms max=4.37s    p(90)=518.07ms p(95)=534.4ms
     iterations.....................: 45033  373.683517/s
     vus............................: 200    min=200      max=200
     vus_max........................: 200    min=200      max=200

running (2m00.5s), 000/200 VUs, 45033 complete and 0 interrupted iterations

2 - After the first initial execution, cold lambda and all available images already saved to the bucket, where we got ~3K more requests being served for the same time

scenarios: (100.00%) 1 scenario, 200 max VUs, 2m30s max duration (incl. graceful stop):
           * default: 200 looping VUs for 2m0s (gracefulStop: 30s)

     data_received..................: 53 MB  442 kB/s
     data_sent......................: 8.4 MB 70 kB/s
     http_req_blocked...............: avg=2.26ms   min=631ns    med=2.24µs   max=612.22ms p(90)=4.04µs   p(95)=6.47µs
     http_req_connecting............: avg=663.23µs min=0s       med=0s       max=215.19ms p(90)=0s       p(95)=0s
     http_req_duration..............: avg=490.8ms  min=199.95ms med=484.02ms max=3.17s    p(90)=514.86ms p(95)=527ms
       { expected_response:true }...: avg=490.53ms min=199.95ms med=484.02ms max=2.4s     p(90)=514.85ms p(95)=526.99ms
     http_req_failed................: 0.01%  ✓ 5         ✗ 48754
     http_req_receiving.............: avg=108.86µs min=12.44µs  med=42.68µs  max=17.62ms  p(90)=69.23µs  p(95)=81.87µs
     http_req_sending...............: avg=14.42µs  min=3.9µs    med=12.14µs  max=786.01µs p(90)=23.03µs  p(95)=30.35µs
     http_req_tls_handshaking.......: avg=1.27ms   min=0s       med=0s       max=332.34ms p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=490.68ms min=199.9ms  med=483.91ms max=3.17s    p(90)=514.75ms p(95)=526.89ms
     http_reqs......................: 48759  404.56812/s
     iteration_duration.............: avg=493.16ms min=200.05ms med=484.11ms max=3.17s    p(90)=514.96ms p(95)=527.1ms
     iterations.....................: 48759  404.56812/s
     vus............................: 200    min=200     max=200
     vus_max........................: 200    min=200     max=200

running (2m00.5s), 000/200 VUs, 48759 complete and 0 interrupted iterations
Categorias
PHP Programação

A bref AWS PHP story – Part 1

The PHP language is a true and good alternative for Serverless applications. PHP is a fast and flexible programming language, and there are many business treasures inside PHP applications, business logic running well for years inside company codebases worldwide.

We don't need to look at PHP as a language that could not run inside a modernized stack. We can move some of this code without total refactoring to Serverless applications, benefiting from an already proven successful code. And we know we all have flows suitable to run as a lambda function.

And not only legacy code. New features are also perfect candidates to be run in PHP and lambdas due to the team's experience, consistency of the technology stack, speed, etc. PHP has served the world well and will remain operating well. PHP is alive.

Table of contents:

  1. The series
  2. Functions
  3. Code
    1. Requirements
    2. The lambda
  4. Wrap-up

The Serie

I am starting a series as a walkthrough for PHP into Serverless, specifically to run as lambdas functions.

We will use Bref, a composer package, to deploy PHP applications to AWS.

Bref (which means "brief" in french) comes as an open source Composer package and helps you deploy PHP applications to AWS and run them on AWS Lambda.
https://bref.sh/docs/

Bref relies on the Serverless framework and AWS access keys to deploy applications.
https://bref.sh/docs/installation.html

The Serverless framework is excellent, but I am more of a fan of AWS CDK. Mainly because it is designed to use an imperative programming framework that speeds up the required infrastructure with excellent constructs on different levels (reasonable defaults), and its output can be run against a test framework (predictability).

There are already some CDK constructs for PHP, but, as far as I see, they are intended to be used by Web Apps lambdas (i.e. using frameworks such as Laravel and Symfony). However, the purpose of this series is to run Event-Driven functions, so I will start using pure CDK constructs.

Functions

As a walkthrough, we will digest the series in affordable bites, starting from simple functions that we will improve as the series continues and we use more AWS resources.

Code

Let's start our PHP lambda function. First, it will begin as an HTTP-based lambda, expecting a request and returning a response. Then, it will execute a trivial piece of computing code: it will return fibonacci.

Get the part 1 source-code in GitHub.

Requirements

(optional) There is a Dockerfile and a docker-compose.yml file for your convenience if you prefer to use docker. It will require you to set AWS environment variables for use by the container.

The lambda

You can check the complete source code for part 1, and we will highlight essential parts from the CDK code, as the PHP code has a few different things from what we are used to code.

The stack creator

In our case, it will create the serverless Stack and related infrastructure, i.e., IAM, lambda function, and URL. If anything else we need, it would be defined and requested by this class.

bin/cdk-stack.ts

export class CdkStack extends Stack {

  // Get Bref layer ARN from https://runtimes.bref.sh/
  public static brefLayerFunctionArn = 'arn:aws:lambda:us-east-1:209497400698:layer:php-82:16';

  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const layer = LayerVersion.fromLayerVersionArn(this, 'php-layer', CdkStack.brefLayerFunctionArn);

    const getLambda = new LambdaFunction(this, 'get', {
      layers: [layer],
      handler: 'get.php',
      runtime: Runtime.PROVIDED_AL2,
      code: Code.fromAsset(join(__dirname, `../assets/get`)),
      functionName: 'part1-get',
    });

    const fnUrl = getLambda.addFunctionUrl({authType: FunctionUrlAuthType.NONE});

    new CfnOutput(this, 'TheUrl', {
      // The .url attributes will return the unique Function URL
      value: fnUrl.url,
    });
  }
}

Highlights

The bref php layer:

public static brefLayerFunctionArn = 'arn:aws:lambda:us-east-1:209497400698:layer:php-82:16';

Where you point your entry point and source code:

      handler: 'get.php',
      runtime: Runtime.PROVIDED_AL2,
      code: Code.fromAsset(join(__dirname, `../assets/get`)), // get.php file inside the zip file located at this path

Using AWS Lambda built-int function URL (we will change to API Gateway later if needed):

    const fnUrl = getLambda.addFunctionUrl({authType: FunctionUrlAuthType.NONE});

Output

You would see CDK outputting the lambda function URL you will use to run your application. Something like:

Outputs:
CdkStack.TheUrl = https://6eoftivwkq4ht65d2h2fwlmsga0vnpfs.lambda-url.us-east-1.on.aws/

The handler

The PHP entry point has usually named a handler to the code. Its responsibility would be to forward the request to a controller or service that will perform the business rules and prepare the response to be returned. This is an HTTP-based lambda; the response should be an HTTP-valid response.

Obs.: You can note by the words above that any existing code that fits in the lambda computing model can be the controller or service to be called by the handler. Theoretically, you only need to create the handler compatible with the lambda environment, instantiate your controller or service, pass whatever it requires as an argument, and then return the expected response.

php/handlers/get.php

<?php
return function ($request) {
    $int = (int) ($request['queryStringParameters']['int'] ?? random_int(1, 300));

    $responseBody = [
        'response' => 'OK. Time: ' . time(),
        'now' => date('Y-m-d H:i:s'),
        'int' => $int,
        'result' => fibonacci($int),
    ];

    $response = new \Symfony\Component\HttpFoundation\JsonResponse($responseBody);

    return (new \Bref\Event\Http\HttpResponse($response->getContent(), $response->headers->all()))->toApiGatewayFormatV2();
};

Highlights

All handlers receive a request object. This is how to access /?int=myValue query string param.

    $int = (int) ($request['queryStringParameters']['int'] ?? random_int(1, 300));

The call to the function fibonacci() is how we would call any other controller or service.

'result' => fibonacci($int),

Using the Symfony Response to validate and prepare a valid HTTP response:

$response = new \Symfony\Component\HttpFoundation\JsonResponse($responseBody);

AWS API Gateway requires a certain Response shape. To be sure to have a valid API Gateway response:

    return (new \Bref\Event\Http\HttpResponse($response->getContent(), $response->headers->all()))->toApiGatewayFormatV2();

And that is it. You can now use your lambda function URL as in the output of the CDK stack above and call it with or without the query string param ?/int=.

➜   curl https://6eoftivwkq4ht65d2h2fwlmsga0vnpfs.lambda-url.us-east-1.on.aws/
{"response":"OK. Time: 1674612343","now":"2023-01-25 02:05:43","int":273,"result":5.05988662735923e+56}%

➜   curl https://6eoftivwkq4ht65d2h2fwlmsga0vnpfs.lambda-url.us-east-1.on.aws/\?int\=500
{"response":"OK. Time: 1674612353","now":"2023-01-25 02:05:53","int":500,"result":1.394232245616977e+104}%

➜   curl https://6eoftivwkq4ht65d2h2fwlmsga0vnpfs.lambda-url.us-east-1.on.aws/\?int\=500
{"response":"OK. Time: 1674612356","now":"2023-01-25 02:05:56","int":500,"result":1.394232245616977e+104}%

The test

We can predict the resources we create via CDK and check if those resources are as expected. The output of the CDK is a CloudFormation template, which we can put under test. That is solid, as unexpected behaviour or changes will fail in our CI pipeline test step.

test/cdk.test.ts

test('Lambda created', () => {
  const app = new cdk.App();
    // WHEN
  const Stack = new Cdk.CdkStack(app, 'MyTestStack');
    // THEN
  const template = Template.fromStack(stack);

  template.hasResourceProperties('AWS::Lambda::Function', {
    Layers: [Cdk.CdkStack.brefLayerFunctionArn]
  });
});

Highlights

We are checking if there is a lambda function and if that function is using the expected specific bref layer:

  template.hasResourceProperties('AWS::Lambda::Function', {
    Layers: [Cdk.CdkStack.brefLayerFunctionArn]
  });

Wrap-up

We have created our Stack and our first simple HTTP-based PHP lambda function using CDK (with tests). Next, we will improve our lambda to use more AWS resources and communication with more complex application services.

Categorias
Tropeçando

Tropeçando 106

5 Constant Lists That Give Context to your Integers and Strings

Enum i a great feature of modern software development. Here you will find five lists that lives in Enums (or Enum-like) that add lots of context for your code. It will look better and cleaner.

Validate all the things: improve your security with input validation!

If there's one habit that can make software more secure, it's probably input validation. Here's how to apply OWASP Proactive Control C5 (Validate All Inputs) to your code.

TypeScript Utility Types: The 6 Most Useful

Write better typescript code by using typescript utility types. Record, Partial, Required, Omit, Pick, Exclude utilities.

Query parameter data types and performance

Recently, I could help solve a “mysterious” performance problem for a customer. The problem turned out to be a badly chosen query parameter type, which led to poor query performance. After working on this customer’s case, I realized that the meaning of the data type of a query parameter is not universally understood, which is why I decided to write this article.

Terraform Best Practices

Building Serverless Applications That Scale The Perfect Amount

Great reasoning about how to think about the architecture that scale on Serverless, thinking about the load and costs.

Run a PHP application on AWS Fargate

An example for a pipeline to configure and deploy a PHP application on AWS Fargate.

6 Signs Your Daily Standups Aren’t Working

Architecture Decision Records help you, your team, and future teams

Decisions are made everyday and often the number of daily decisions make us forget older ones. Keeping a record of the decisions is a great tool to revisit what was done and also be more confident that a change can be made, when a previous statement become obsolete somehow. ADRs are a great tool for a mature software.

Waiting for PostgreSQL 15 – Add support for MERGE SQL command

MERGE SQL commands is able to perform INSERT/UPDATE/DELETE based on a base query and some conditions. This is very useful for some business logic that can be applied directly on the database data.

Categorias
Tropeçando

Tropeçando 105

CQRS and Event Sourcing implementation in PHP

A walk-through of using CQRS along with Event Sourcering using PHP.

Is my autovacuum configured properly?

Some tips to identify if you need to tune your autovacuum configurations. A proper house cleaning can improve your database health and performance.

Learn how to migrate to the PHP framework Symfony

SensioLabs and Smile released a joint white paper “PHP framework migration: from legacy to Symfony” explaining how to migrate to modern PHP frameworks like Symfony. Find a selection of the key information in this infographic design by SensioLabs.

trufflehog

Find leaked credentials. Search on your repos, source-code, etc.

Why we don’t use a staging environment

Squeaky deploys their code directly from laptops to production environments. The blog posts details their strategies, such as a good suite of tests, clear branch strategy and use of feature flags.

Scaling containers on AWS in 2022

Benchmarking for different types of workloads and scales capabilities on AWS services in 2022: lambda, EKS, ECS, Fargate...

Building well-architected serverless applications: Introduction

Multi-part series addressing each of the questions within the Serverless Lens of the Well-Architected Tool.

Comparing Workflows

Comparision of different types of git flows: centralized, feature branch, gitflow and fork flow. Simple comparision, but easy to get the sense of their use cases.

Construct Hub

Find libraries for AWS Cloud Development Kit (AWS CDK), which generates AWS CloudFormation templates, CDK for Terraform (CDKtf), which generates HashiCorp Terraform configuration files, and CDK for Kubernetes (CDK8s), which generates Kubernetes manifests.

Too much magic?

A good thinking about the "magic" under some awesomeness that are provided by frameworks or libraries. Although they are good for quicker development, there is good to think a little bit more about how and when use it when we have a software that we aim to last longer and get to the phase of greater maintainability.

Categorias
Tropeçando

Tropeçando 102

OWASP TOP 10

Each year, OWASP (the Open Web Application Security Project) publishes the top ten security vulnerabilities. It represents a broad consensus about the most critical security risks to web applications. Click through on the lessons below to learn more about how to protect against each security risk.

Your Product Owner Is Not Your Product Manager

Your Product Owner Is Not Your Product Manager. Product management has evolved to encompass numerous roles and responsibilities. Leaders looking to hire a product professional must consider what skills and knowledge their business needs demand.

While the market has evolved and will continue to evolve, there remains a need for both a product owner’s and a product manager’s skills and expertise. By considering the nature and scale of a project and understanding the skills and responsibilities associated with each of these distinct roles, leaders can ensure they hire the right person to help them develop and launch products successfully.

Insert-Only Tables and Autovacuum Issues Prior to PostgreSQL 13

If you have write-only tables (or heavy, heavy writes), you may need to check this post. Autovacuum has some issues before PostgreSQL 13, and you might have some great workarounds to use until upgrading your database version.

Enterprise CI/CD best practices

Free book with 23 best practices to apply to your CI/CD pipeline. Those best practices aim to help you design (or use as a checklist) a solid pipeline for your software.

A war story about COVID, cloud, and cost. And why serverless wins.

Nice story about serverless outcomes and potential. Based on COVID-19 pushing of infrastructure and computing services, billing is an important subject. The article has an excellent example of how both scale environment and low bill costs work together on a serverless tech stack.

Categorias
Tropeçando

Tropeçando 98

Operating Lambda: Debugging code – Part 1
Operating Lambda: Debugging configurations – Part 2
Operating Lambda: Debugging configurations – Part 3

In the Operating Lambda series, I cover important topics for developers, architects, and systems administrators who are managing AWS Lambda-based applications. This three-part series discusses core debugging concepts for Lambda-based applications.

Those pesky pull request reviews

They’re everywhere. In Slack: “hey, can I get a review on this?” In email: “Your review is requested!” In JIRA: “8 user stories In-Progress” (but code-complete). In your repository: 5 open pull requests. They’re slowing your delivery. They’re interrupting your developers.

How can we get people to review pull requests faster??

Operating Lambda: Using CloudWatch Logs Insights

In the Operating Lambda series, I cover important topics for developers, architects, and systems administrators who are managing AWS Lambda-based applications. This three-part series discusses monitoring and observability for Lambda-based applications and covers:

  • Using Amazon CloudWatch, CloudWatch Logs Insights, and AWS X-Ray to apply monitoring
    across services.
  • How existing monitoring concepts apply to Lambda-based applications.
  • Troubleshooting application issues in an example walkthrough.
    This post explains how to use CloudWatch Logs Insights in your serverless applications.

CDK Lambda Deployment takes about a minute - how about sub second Function Code Deployment?

Creation of Lambda infrastructure with the CDK is really powerful. Updating the Function code is really slow. Here is a fix for that to get to a sub-second Lambda function deployment time.

Best practices for developing cloud applications with AWS CDK

In this post, we discuss strategies for organizing the development of complex cloud applications with large teams, using the AWS Cloud Development Kit (AWS CDK) as a central technology. AWS CDK allows developers and administrators to define their cloud applications using a familiar programming language, such as TypeScript, Python, Java, or C#. Applications are organized into stages, stacks, and constructs, which allows for modular design techniques in both runtime logic (such as AWS Lambda code or containerized services) and infrastructure components such as Amazon Simple Storage Service (Amazon S3) buckets, Amazon Relational Database Service (Amazon RDS) databases, and network infrastructure.

Categorias
Tropeçando

Tropeçando 97

The Missing Guide to AWS API Gateway Access Logs

In this post, we’re continuing the deep dive on API Gateway. Here, we’ll be looking at API Gateway access logging. Access logging can save your bacon when debugging a gnarly API Gateway issue, but you need to understand some nuance before you can use it correctly. We’ll dig into the details here so that you’ll be logging like Paul Bunyan in no time.

Ready for changes with Hexagonal Architecture

Netflix considerations related to the decisions of using Hexagonal Architecture

OAuth Patterns and Anti-Patterns RefCard

Modern, more secure recommendations continue to replace some of OAuth's original elements as the protocol evolves. Securing access to APIs and other resources and data effectively under OAuth 2.0 requires first learning the components and tools it involves.

Can auto_explain (with timing) have low overhead?

Some benchmarks for use of auto_explain. It seems great to be enabled on production.

Here we’ll be looking into the overhead of auto_explain. Many places warn about its overhead, but I’ve found concrete information difficult to come by.

Setting up SSL authentication for PostgreSQL

PostgreSQL is a secure database and we want to keep it that way. It makes sense, then, to consider SSL to encrypt the connection between client and server. This posting will help you to set up SSL authentication for PostgreSQL properly, and hopefully also to understand some background information to make your database more secure.

Categorias
Tropeçando

Tropeçando 95

Windy - TailwindCSS

Transform every element on any website into Tailwind CSS

AWS Workshops

This website lists workshops created by the teams at Amazon Web Services (AWS). Workshops are hands-on events designed to teach or introduce practical skills, techniques, or concepts which you can use to solve business problems.

Well-Architected AWS

The Well-Architected framework has been developed to help cloud architects build the most secure, high-performing, resilient, and efficient infrastructure possible for their applications. This framework provides a consistent approach for customers and partners to evaluate architectures, and provides guidance to help implement designs that will scale with your application needs over time.

This repository contains documentation and code in the format of hands-on labs to help you learn, measure, and build using architectural best practices. The labs are categorized into levels, where 100 is introductory, 200/300 is intermediate and 400 is advanced.

Fallacies of distributed computing

false assumptions that programmers new to distributed applications invariably make.

Understanding DynamoDB Condition Expressions

Some use cases to understand this powerful yet misunderstood feature of DynamoDB. There are also examples of bad use of it.