AWS Lambda com Java 25 e GraalVM
Usar Lambda com java já foi motivo de risos e muitos falariam que é loucura, porem desde que a compilação nativa se tornou realidade este cenário vem mudando desde o java 11 quando as primeiras compilações nativas existiram.
Mas desde o Java 17 tudo foi avançando de forma muito rápida e hoje com o Java 25 se tornou algo totalmente tangível e sem nenhuma perda ao comparar com Golang, python que sempre foram as primeiras escolhas quando o assunto era Lambda.
Claro que existem tradeoffs a serem considerados e algumas configurações extras, nem tudo são flores mas eu acredito que logo tudo será contornado e melhorado
Bora por a mão na massa então, crie um projeto novo em java com maven, aqui estou com o maven 3.9.12 e java 25, versão do graalvm é a 25 também.
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-runtime-interface-client</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>3.16.1</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>sqs</artifactId>
<version>2.41.20</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>url-connection-client</artifactId>
<version>2.41.20</version>
</dependency>
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.42</version>
</dependency>
<!-- Provide a simple SLF4J binding so the NOP logger warning goes away during tests/runtime -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.36</version>
<scope>runtime</scope>
</dependency>
</dependencies>
Acima são as dependências essenciais, abaixo vamos as configurações de build
<plugins>
...
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.11.4</version>
<configuration>
<imageName>bootstrap</imageName>
<mainClass>br.com.tiagoiwamoto.awslambdasamples.sqs.SqsLambdaHandler</mainClass>
</configuration>
</plugin>
...
</plugins>
O plugin acima é essencial para que o maven entenda que ao gerar a imagem nativa seja com esse nome ‘bootstrap’
E a parte do Profiles, que é a mais importante, mas talvez a que vai levar mais tempo, pois dentro dela existe o buildArgs que você vai passando tudo que precisa ser inicializado em tempo de runtime ou no build do runtime e até mesmo configurações que deseja que seja incluido no processo do build do nativo, alem de apontar para arquivos de reflections,resources, aqui eu acredito ser a segunda parte mais chata a primeira é o reflections que vamos ver já já.
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.11.4</version>
<executions>
<execution>
<id>build-native</id>
<goals>
<goal>compile-no-fork</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<mainClass>br.com.tiagoiwamoto.awslambdasamples.sqs.SqsLambdaHandler</mainClass>
<skipNativeTests>true</skipNativeTests>
<buildArgs>
...
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Se deu certo ao executar mvn clean package -Pnative você vai ver na pasta target 3 arquivos, sendo 2 deles os tradicionais .jar e um arquivo sem extensão que é o binario e com o nome informado no plugin do graalvm.

agora é executar seu binário e no meu caso coloquei só um ‘Starting Lambda’ para testar
static void main() {
log.info("Starting Lambda");
}

Com isso podemos implementar nossa lambda.
Para a compilação nativa não importa até a data de hoje (15/02/2026) você colocar aqueles @Override por conta do RequestHandler, nem precisa extender a classe na verdade. Isso porque a compilação nativa chama sempre o metodo main() e a partir dai você precisa implementar.
Em um próximo post vou mostrar como implementar um lambda sendo acionado por um Aws SQS que é um fluxo super comum.