Yes, there is a better solution.
Basically, you are right, Lambdas should be treated as stateless.
However, in AWS Lambda there is concept of container reuse. Which means that if you invoke Lambdas on a frequent basis then it is highly possible that the same container which served your previous request will be used for serving your current request. And if that happens, then you get the previous Execution Context which includes all declarations and database connections (except the handler code) as is from the previous execution.
Following is what is documented for AWS Lambda container reuse
After a Lambda function is executed, AWS Lambda maintains the
Execution Context for some time in anticipation of another Lambda
function invocation. In effect, the service freezes the Execution
Context after a Lambda function completes, and thaws the context for
reuse, if AWS Lambda chooses to reuse the context when the Lambda
function is invoked again. This Execution Context reuse approach has
the following implications:
- Any declarations in your Lambda function code (outside the handler code, see Programming Model) remains initialized, providing additional
optimization when the function is invoked again. For example, if your
Lambda function establishes a database connection, instead of
reestablishing the connection, the original connection is used in
subsequent invocations. We suggest adding logic in your code to check
if a connection exists before creating one.
For more details check here